git 5.1.0 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +45 -0
  3. data/CONTRIBUTING.md +185 -165
  4. data/LICENSE +1 -1
  5. data/README.md +151 -151
  6. data/git.gemspec +35 -3
  7. data/lib/git/command_line/base.rb +1 -2
  8. data/lib/git/commands/base.rb +1 -1
  9. data/lib/git/commands/cat_file/raw.rb +8 -7
  10. data/lib/git/repository/branching.rb +79 -5
  11. data/lib/git/version.rb +1 -1
  12. metadata +5 -94
  13. data/.claude/commands/address-copilot-reviews.md +0 -14
  14. data/.claude/settings.json +0 -16
  15. data/.claude/skills +0 -1
  16. data/.commitlintrc.yml +0 -38
  17. data/.dockerignore +0 -27
  18. data/.github/copilot-instructions.md +0 -30
  19. data/.github/hooks/bin-setup-on-worktree.json +0 -11
  20. data/.github/hooks/run-bin-setup-once.sh +0 -20
  21. data/.github/issue_template.md +0 -15
  22. data/.github/prompts/iteratively-address-copilot-reviews.prompt.md +0 -188
  23. data/.github/pull_request_template.md +0 -21
  24. data/.github/skills/breaking-change-analysis/SKILL.md +0 -99
  25. data/.github/skills/ci-cd-troubleshooting/SKILL.md +0 -264
  26. data/.github/skills/command-implementation/REFERENCE.md +0 -994
  27. data/.github/skills/command-implementation/SKILL.md +0 -230
  28. data/.github/skills/command-test-conventions/SKILL.md +0 -664
  29. data/.github/skills/command-yard-documentation/SKILL.md +0 -434
  30. data/.github/skills/dependency-management/SKILL.md +0 -72
  31. data/.github/skills/development-workflow/SKILL.md +0 -512
  32. data/.github/skills/facade-implementation/REFERENCE.md +0 -837
  33. data/.github/skills/facade-implementation/SKILL.md +0 -269
  34. data/.github/skills/facade-test-conventions/SKILL.md +0 -391
  35. data/.github/skills/facade-yard-documentation/SKILL.md +0 -435
  36. data/.github/skills/make-skill-template/SKILL.md +0 -226
  37. data/.github/skills/pr-readiness-review/SKILL.md +0 -205
  38. data/.github/skills/project-context/SKILL.md +0 -306
  39. data/.github/skills/pull-request-review/SKILL.md +0 -168
  40. data/.github/skills/rebase/SKILL.md +0 -148
  41. data/.github/skills/refactor-command-to-commandlineresult/SKILL.md +0 -131
  42. data/.github/skills/release-management/SKILL.md +0 -125
  43. data/.github/skills/resolve-feedback/SKILL.md +0 -288
  44. data/.github/skills/review-arguments-dsl/CHECKLIST.md +0 -788
  45. data/.github/skills/review-arguments-dsl/SKILL.md +0 -214
  46. data/.github/skills/review-cross-command-consistency/SKILL.md +0 -139
  47. data/.github/skills/reviewing-skills/SKILL.md +0 -214
  48. data/.github/skills/rspec-unit-testing-standards/SKILL.md +0 -685
  49. data/.github/skills/tdd-refactor-step/SKILL.md +0 -236
  50. data/.github/skills/test-debugging/SKILL.md +0 -161
  51. data/.github/skills/yard-documentation/SKILL.md +0 -981
  52. data/.github/skills/yard-documentation/element-rules.md +0 -162
  53. data/.github/skills-deprecated/README.md +0 -21
  54. data/.github/skills-deprecated/extract-command-from-lib/SKILL.md +0 -487
  55. data/.github/skills-deprecated/extract-facade-from-base-lib/KEYWORD_ARG_REMEDIATION.md +0 -22
  56. data/.github/skills-deprecated/extract-facade-from-base-lib/SKILL.md +0 -600
  57. data/.github/skills-deprecated/review-backward-compatibility/SKILL.md +0 -275
  58. data/.github/workflows/continuous_integration.yml +0 -358
  59. data/.github/workflows/enforce_conventional_commits.yml +0 -35
  60. data/.github/workflows/experimental_continuous_integration.yml +0 -59
  61. data/.github/workflows/release.yml +0 -52
  62. data/.github/workflows/warm_bundler_caches.yml +0 -82
  63. data/.gitignore +0 -30
  64. data/.husky/commit-msg +0 -1
  65. data/.husky/pre-commit +0 -13
  66. data/.release-please-config.json +0 -36
  67. data/.release-please-manifest.json +0 -3
  68. data/.rspec +0 -2
  69. data/.rubocop.yml +0 -44
  70. data/.rubocop_todo.yml +0 -30
  71. data/.yard-lint.yml +0 -75
  72. data/CLAUDE.md +0 -11
  73. data/Gemfile +0 -22
  74. data/Rakefile +0 -41
  75. data/docker/test/Dockerfile +0 -32
  76. data/docker/test/docker-compose.yml +0 -0
  77. data/package.json +0 -10
  78. data/redesign/1_architecture_existing.md +0 -102
  79. data/redesign/2_architecture_redesign.md +0 -449
  80. data/redesign/3_architecture_implementation.md +0 -1623
  81. data/redesign/Phase 4 - Step A.md +0 -366
  82. data/redesign/Phase 4 - Step B.md +0 -921
  83. data/redesign/Phase 4 - Step C.md +0 -833
  84. data/redesign/beta_release.md +0 -107
  85. data/redesign/branch_parse_refactor_plan.md +0 -163
  86. data/redesign/c1a-public-api-scope.tsv +0 -256
  87. data/redesign/c1c2_audit.md +0 -566
  88. data/redesign/c1c2_bucket6_lib_orphans.md +0 -626
  89. data/redesign/config_design.rb +0 -501
  90. data/redesign/index.md +0 -34
  91. data/redesign/info_object_migration_plan.md +0 -126
  92. data/redesign/integration_test_analysis.md +0 -521
  93. data/redesign/phase-4-step-b-test-audit.tsv +0 -485
  94. data/redesign/remote_refactor_plan.md +0 -164
  95. data/redesign/reverse_dependencies.sql +0 -44
  96. data/tasks/gem_tasks.rake +0 -14
  97. data/tasks/npm_tasks.rake +0 -7
  98. data/tasks/rspec.rake +0 -111
  99. data/tasks/rubocop.rake +0 -5
  100. data/tasks/test_gem.rake +0 -12
  101. data/tasks/yard.rake +0 -57
@@ -1,148 +0,0 @@
1
- ---
2
- name: rebase
3
- description: 'Rebases the current branch onto origin/main, resolves rebase conflicts, and force-pushes with lease using non-interactive Git commands that never open an editor. Use when updating a feature branch from main, handling rebase conflicts, or rewriting branch history before updating a pull request.'
4
- ---
5
-
6
- # Rebase
7
-
8
- Rebase the current branch on `origin/main`, resolve conflicts, and force-push
9
- the rewritten history without opening an editor.
10
-
11
- ## Contents
12
-
13
- - [Contents](#contents)
14
- - [How to use this skill](#how-to-use-this-skill)
15
- - [Related skills](#related-skills)
16
- - [Prerequisites](#prerequisites)
17
- - [Safety rules](#safety-rules)
18
- - [Workflow](#workflow)
19
- - [Step 1: Preflight checks and fetch](#step-1-preflight-checks-and-fetch)
20
- - [Step 2: Start rebase on origin/main](#step-2-start-rebase-on-originmain)
21
- - [Step 3: Resolve conflicts and continue](#step-3-resolve-conflicts-and-continue)
22
- - [Step 4: Verify the rebased branch](#step-4-verify-the-rebased-branch)
23
- - [Step 5: Force-push with lease](#step-5-force-push-with-lease)
24
- - [Troubleshooting](#troubleshooting)
25
-
26
- ## How to use this skill
27
-
28
- Attach this file to your Copilot Chat context, then invoke it when the current
29
- branch needs to be rebased onto `origin/main` and pushed.
30
-
31
- ## Related skills
32
-
33
- - [Resolve Feedback](../resolve-feedback/SKILL.md) — follow-up workflow for
34
- addressing PR review comments after rebasing
35
- - [PR Readiness Review](../pr-readiness-review/SKILL.md) — final validation
36
- before opening or updating a pull request
37
-
38
- ## Prerequisites
39
-
40
- - `git` is installed and authenticated for the remote.
41
- - The branch is a topic branch with an upstream on `origin`.
42
- - The working tree is clean before rebasing.
43
-
44
- ## Safety rules
45
-
46
- These rules are mandatory:
47
-
48
- - Never run this workflow on `main` or `4.x`.
49
- - Always fetch `origin` immediately before rebasing.
50
- - Always run rebase commands with `GIT_EDITOR=:` and `GIT_SEQUENCE_EDITOR=:` so
51
- no editor opens.
52
- - Force-push only with `--force-with-lease`.
53
-
54
- ## Workflow
55
-
56
- 1. [Preflight checks and fetch](#step-1-preflight-checks-and-fetch)
57
- 2. [Start rebase on origin/main](#step-2-start-rebase-on-originmain)
58
- 3. [Resolve conflicts and continue](#step-3-resolve-conflicts-and-continue)
59
- 4. [Verify the rebased branch](#step-4-verify-the-rebased-branch)
60
- 5. [Force-push with lease](#step-5-force-push-with-lease)
61
-
62
- ## Step 1: Preflight checks and fetch
63
-
64
- ```bash
65
- git branch --show-current
66
- git status --short --branch
67
- git fetch --prune origin
68
- ```
69
-
70
- If the current branch is `main` or `4.x`, stop and ask the user to switch to a
71
- topic branch first.
72
-
73
- If `git status --short --branch` shows uncommitted changes, stop and ask the
74
- user whether to commit or stash before continuing.
75
-
76
- ## Step 2: Start rebase on origin/main
77
-
78
- ```bash
79
- GIT_EDITOR=: GIT_SEQUENCE_EDITOR=: git rebase origin/main
80
- ```
81
-
82
- If the command succeeds, continue to Step 4. If it stops with conflicts, go to
83
- Step 3.
84
-
85
- ## Step 3: Resolve conflicts and continue
86
-
87
- Repeat until the rebase completes:
88
-
89
- 1. Inspect conflicted files:
90
-
91
- ```bash
92
- git status --short
93
- ```
94
-
95
- 2. Edit conflicted files, remove conflict markers, and keep the intended final
96
- content.
97
-
98
- 3. Stage resolved files:
99
-
100
- ```bash
101
- git add <resolved-path> [<resolved-path>...]
102
- ```
103
-
104
- 4. Continue the rebase without opening an editor:
105
-
106
- ```bash
107
- GIT_EDITOR=: GIT_SEQUENCE_EDITOR=: git rebase --continue
108
- ```
109
-
110
- 5. If Git reports an empty patch after conflict resolution, skip that commit:
111
-
112
- ```bash
113
- GIT_EDITOR=: GIT_SEQUENCE_EDITOR=: git rebase --skip
114
- ```
115
-
116
- If the rebase cannot be completed safely, abort and report back:
117
-
118
- ```bash
119
- git rebase --abort
120
- ```
121
-
122
- ## Step 4: Verify the rebased branch
123
-
124
- ```bash
125
- git status --short --branch
126
- git merge-base --is-ancestor origin/main HEAD
127
- git --no-pager log --oneline --decorate --max-count=15
128
- ```
129
-
130
- `git merge-base --is-ancestor origin/main HEAD` must exit successfully.
131
-
132
- ## Step 5: Force-push with lease
133
-
134
- ```bash
135
- git push --force-with-lease
136
- ```
137
-
138
- If push is rejected, fetch and reconcile remote updates before retrying. Never
139
- replace this with plain `--force`.
140
-
141
- ## Troubleshooting
142
-
143
- | Issue | Solution |
144
- | ----- | -------- |
145
- | Rebase stops with conflicts | Resolve files, `git add`, then run `GIT_EDITOR=: GIT_SEQUENCE_EDITOR=: git rebase --continue`. |
146
- | Rebase continue opens an editor | Re-run with both `GIT_EDITOR=:` and `GIT_SEQUENCE_EDITOR=:` prefixes. |
147
- | `--force-with-lease` push rejected | Run `git fetch origin`, inspect divergence, reconcile, and retry `--force-with-lease`. |
148
- | Need to abandon rebasing attempt | Run `git rebase --abort` and report the reason to the user. |
@@ -1,131 +0,0 @@
1
- ---
2
- name: refactor-command-to-commandlineresult
3
- description: "Migrates a command class that still performs parsing or custom execution logic to return raw Git::CommandLineResult, moving parsing to facade/parser layers. Use during architectural redesign refactoring."
4
- ---
5
-
6
- # Refactor Command to CommandLineResult
7
-
8
- Migrate a command that still performs parsing or custom execution logic to the
9
- `Git::Commands::Base` pattern, so command classes return raw
10
- `Git::CommandLineResult` and parsing moves to facade/parser layers.
11
-
12
- ## Contents
13
-
14
- - [How to use this skill](#how-to-use-this-skill)
15
- - [Prerequisites](#prerequisites)
16
- - [Related skills](#related-skills)
17
- - [Target end state](#target-end-state)
18
- - [Refactor steps](#refactor-steps)
19
- - [What to remove from command classes](#what-to-remove-from-command-classes)
20
- - [What to update in tests](#what-to-update-in-tests)
21
- - [YARD updates](#yard-updates)
22
- - [Migration process and internal compatibility](#migration-process-and-internal-compatibility)
23
-
24
- ## How to use this skill
25
-
26
- Attach this file to your Copilot Chat context, then invoke it with the command
27
- class or source file to migrate. Examples:
28
-
29
- ```text
30
- Using the Refactor Command to CommandLineResult skill, migrate
31
- Git::Commands::Stash::Pop to the Base pattern.
32
- ```
33
-
34
- ```text
35
- Refactor Command to CommandLineResult: lib/git/commands/branch/delete.rb
36
- ```
37
-
38
- The invocation needs the command class name or file path of the command to
39
- refactor.
40
-
41
- ## Prerequisites
42
-
43
- Before starting, you **MUST** load the following skill(s) in their entirety:
44
-
45
- - [YARD Documentation](../yard-documentation/SKILL.md) — authoritative
46
- source for YARD formatting rules and writing standards;
47
-
48
- ## Related skills
49
-
50
- - [Command Implementation](../command-implementation/SKILL.md) — canonical class-shape checklist, phased
51
- rollout gates, and internal compatibility contracts
52
- - [Review Arguments DSL](../review-arguments-dsl/SKILL.md) — verifying DSL entries match git CLI
53
- - [Command Test Conventions](../command-test-conventions/SKILL.md) — unit/integration test conventions for command classes
54
- - [Facade Implementation](../facade-implementation/SKILL.md) — preserving `Git::Repository::*` return-value contracts
55
-
56
- ## Target end state
57
-
58
- ```ruby
59
- class SomeCommand < Git::Commands::Base
60
- arguments do
61
- ...
62
- end
63
-
64
- # optional for non-zero successful exits
65
- # rationale comment
66
- # allow_exit_status 0..1
67
-
68
- # @!method call(*, **)
69
- #
70
- # @overload call(**options)
71
- #
72
- # Execute the git ... command.
73
- #
74
- # @return [Git::CommandLineResult]
75
- end
76
- ```
77
-
78
- ## Refactor steps
79
-
80
- 1. Move parsing/transforming logic out of command class into caller/facade/parser.
81
- 2. Replace legacy `ARGS` constant + custom `initialize` with `arguments do` +
82
- inheritance from `Base`.
83
- 3. Remove custom `#call` body and add `# @!method call(*, **)` YARD directive.
84
- 4. If command requires non-default success exits, add `allow_exit_status` with
85
- rationale comment.
86
- 5. Update callers to consume `CommandLineResult` and parse `result.stdout` where
87
- needed.
88
-
89
- ## What to remove from command classes
90
-
91
- - parser invocations
92
- - output transformation logic
93
- - `literal` entries for policy/output-control flags (e.g. `literal '--no-edit'`,
94
- `literal '--verbose'`, `literal '--no-progress'`, `literal '--no-color'`) —
95
- command classes are neutral, faithful representations of the git CLI; convert to
96
- `flag_option` / `value_option` so the facade can pass the policy value. See
97
- "Command-layer neutrality" in CONTRIBUTING.md.
98
- - manual `raise_on_failure` / manual exit-code checks (unless temporarily needed in
99
- an unmigrated class)
100
- - duplicated bind/execute logic
101
-
102
- ## What to update in tests
103
-
104
- - unit specs should assert CLI args and `CommandLineResult` behavior
105
- - remove parsed-object assertions from command unit specs
106
- - move parsing expectations to parser/facade tests
107
- - include `raise_on_failure: false` in mocked command expectations
108
-
109
- ## YARD updates
110
-
111
- - update `@return` to `Git::CommandLineResult`
112
- - keep command-specific `@overload` docs nested under `# @!method call(*, **)` directive
113
- - ensure `@raise` wording reflects allowed range behavior
114
- - tag short descriptions must not end with punctuation (no trailing period, comma,
115
- or colon)
116
- - multi-paragraph tag descriptions must have a blank comment line (`#`) between the
117
- short description and each continuation paragraph
118
-
119
- ## Migration process and internal compatibility
120
-
121
- See [Command Implementation](../command-implementation/SKILL.md) for the canonical phased rollout checklist
122
- and internal compatibility contract. In summary:
123
-
124
- - **always work on a feature branch** — never commit or push directly to `main`;
125
- create a branch before starting (`git checkout -b <feature-branch-name>`) and
126
- open a pull request when the slice is ready
127
- - perform refactor in phased slices (pilot/family)
128
- - keep each slice independently revertible
129
- - do not mix unrelated behavior changes with refactor-only changes
130
- - pass slice gates: `bundle exec rspec`, `bundle exec rake test`,
131
- `bundle exec rubocop`, `bundle exec rake yard`
@@ -1,125 +0,0 @@
1
- ---
2
- name: release-management
3
- description: "Prepares and publishes new releases of the ruby-git gem including version bumps, changelog updates, tagging, and gem publishing. Use when preparing a release or checking release readiness."
4
- ---
5
-
6
- # Release Management Workflow
7
-
8
- This workflow describes how releases are managed for the ruby-git gem.
9
-
10
- ## Contents
11
-
12
- - [How to use this skill](#how-to-use-this-skill)
13
- - [Related skills](#related-skills)
14
- - [How Releases Work](#how-releases-work)
15
- - [Developer Responsibilities](#developer-responsibilities)
16
- - [Checking Release Readiness](#checking-release-readiness)
17
- - [What NOT to Do](#what-not-to-do)
18
- - [Useful Commands](#useful-commands)
19
-
20
- ## How to use this skill
21
-
22
- Attach this file to your Copilot Chat context when preparing a release, verifying
23
- release readiness, or answering questions about versioning and publishing flow.
24
-
25
- ## Related skills
26
-
27
- - [Dependency Management](../dependency-management/SKILL.md) — dependency updates
28
- that affect release content and risk
29
- - [PR Readiness Review](../pr-readiness-review/SKILL.md) — ensure changes are
30
- release-ready before merge
31
- - [Breaking Change Analysis](../breaking-change-analysis/SKILL.md) — evaluate and
32
- communicate major-version impact
33
-
34
- ## How Releases Work
35
-
36
- Releases are **fully automated** via
37
- [release-please](https://github.com/googleapis/release-please) and the
38
- `.github/workflows/release.yml` workflow:
39
-
40
- 1. Developers merge PRs with **conventional commit** messages into `main`
41
- 2. release-please automatically opens (and keeps updated) a **release PR** that
42
- bumps `lib/git/version.rb` and regenerates `CHANGELOG.md`
43
- 3. When a maintainer merges the release PR, release-please creates a **GitHub
44
- release** with a tag
45
- 4. The workflow then **publishes the gem** to RubyGems.org via `rubygems/release-gem`
46
-
47
- Key config files:
48
-
49
- | File | Purpose |
50
- | ---- | ------- |
51
- | `.release-please-config.json` | Release-please settings (release type, changelog sections, versioning strategy) |
52
- | `.release-please-manifest.json` | Tracks the current released version |
53
- | `lib/git/version.rb` | Version constant (updated automatically by release-please) |
54
- | `CHANGELOG.md` | Release history (updated automatically by release-please) |
55
-
56
- The versioning strategy is `prerelease` with `beta` as the prerelease type. The
57
- config also sets `bump-minor-pre-major: true` and `bump-patch-for-minor-pre-major: true`.
58
-
59
- ## Developer Responsibilities
60
-
61
- The only thing developers need to do for releases is **use conventional commit
62
- messages**. release-please determines the version bump from commit types:
63
-
64
- - `fix:` → **patch** bump
65
- - `feat:` → **minor** bump
66
- - `feat!:` or `BREAKING CHANGE:` footer → **major** bump
67
-
68
- Everything else (version bump, changelog, tag, gem push) is automated. Do **not**
69
- manually edit `lib/git/version.rb` or `CHANGELOG.md`.
70
-
71
- ## Checking Release Readiness
72
-
73
- Before a maintainer merges a release PR:
74
-
75
- 1. **Ensure CI passes on `main`:**
76
-
77
- ```bash
78
- bundle exec rake default
79
- ```
80
-
81
- 2. **Review unreleased changes since last tag:**
82
-
83
- ```bash
84
- git log $(git describe --tags --abbrev=0)..HEAD --oneline
85
- ```
86
-
87
- 3. **Check for open blockers:**
88
-
89
- ```bash
90
- gh issue list --label "bug" --state open
91
- ```
92
-
93
- 4. **Review the release PR** — verify the auto-generated changelog and version
94
- bump look correct.
95
-
96
- ## What NOT to Do
97
-
98
- - Do **not** manually bump `lib/git/version.rb` — release-please does this
99
- - Do **not** manually edit `CHANGELOG.md` — it is auto-generated from commits
100
- - Do **not** manually create tags — release-please creates them on merge
101
- - Do **not** manually `gem push` — the workflow handles publishing
102
- - Do **not** force-push or rebase the release PR — release-please manages it
103
-
104
- ## Useful Commands
105
-
106
- ```bash
107
- # View recent tags
108
- git tag -l --sort=-v:refname | head -10
109
-
110
- # List commits since last release
111
- git log $(git describe --tags --abbrev=0)..HEAD --oneline
112
-
113
- # Compare with previous release
114
- git diff $(git describe --tags --abbrev=0)..HEAD
115
-
116
- # Check current version
117
- ruby -e "require_relative 'lib/git/version'; puts Git::VERSION"
118
-
119
- # View release-please config
120
- cat .release-please-config.json | jq .
121
-
122
- # Build gem locally (for testing only)
123
- bundle exec rake build
124
- gem install pkg/git-*.gem
125
- ```
@@ -1,288 +0,0 @@
1
- ---
2
- name: resolve-feedback
3
- description: 'Resolves unresolved pull request review threads on the current branch, folds each fix into the existing commit that last touched the same file, force-pushes with lease, and requests a fresh Copilot review. Use when addressing PR feedback, resolving review comments or threads, amending fixes into prior commits, or asking Copilot to re-review after changes.'
4
- ---
5
-
6
- # Resolve Feedback
7
-
8
- Address the unresolved review threads on the pull request for the current
9
- branch, folding each fix into the existing commit that last touched the affected
10
- file, then force-push and request another Copilot review.
11
-
12
- ## Contents
13
-
14
- - [Contents](#contents)
15
- - [How to use this skill](#how-to-use-this-skill)
16
- - [Related skills](#related-skills)
17
- - [Prerequisites](#prerequisites)
18
- - [Terms](#terms)
19
- - [Safety and stop points](#safety-and-stop-points)
20
- - [Workflow](#workflow)
21
- - [Step 1: Identify the PR and branch](#step-1-identify-the-pr-and-branch)
22
- - [Step 2: Fetch unresolved review threads](#step-2-fetch-unresolved-review-threads)
23
- - [Step 3: Triage each thread](#step-3-triage-each-thread)
24
- - [Step 4: Implement the changes](#step-4-implement-the-changes)
25
- - [Step 5: Fold each change into the matching commit](#step-5-fold-each-change-into-the-matching-commit)
26
- - [Step 6: Force-push the branch](#step-6-force-push-the-branch)
27
- - [Step 7: Reply to and resolve threads](#step-7-reply-to-and-resolve-threads)
28
- - [Step 8: Request another Copilot review](#step-8-request-another-copilot-review)
29
- - [Troubleshooting](#troubleshooting)
30
-
31
- ## How to use this skill
32
-
33
- Attach this file to your Copilot Chat context and invoke it when a PR has review
34
- feedback to address on the current branch. Work top to bottom. Stop and ask the
35
- user whenever a thread needs a clarification or decision (Step 3) and before the
36
- history-rewriting force-push (Step 6).
37
-
38
- ## Related skills
39
-
40
- - [Pull Request Review](../pull-request-review/SKILL.md) — the review workflow
41
- that produces the threads this skill resolves
42
- - [PR Readiness Review](../pr-readiness-review/SKILL.md) — pre-PR quality gate to
43
- run before pushing follow-up changes
44
- - [Development Workflow](../development-workflow/SKILL.md) — TDD process and
45
- branch rules that govern the fixes made here
46
-
47
- ## Prerequisites
48
-
49
- - The `gh` CLI is installed and authenticated (`gh auth status`).
50
- - The current branch has an open PR and is a topic branch (not `main` or `4.x`).
51
- - The working tree has no unrelated uncommitted changes before starting.
52
-
53
- ## Terms
54
-
55
- - **Unresolved review thread** — a PR review thread whose `isResolved` is
56
- `false` in the GitHub GraphQL API.
57
- - **Base** — the merge-base between the PR base branch and `HEAD`, computed with
58
- `git merge-base origin/<base-branch> HEAD`. All commit lookups are scoped to
59
- `<base>..HEAD` so only this branch's commits are considered.
60
- - **Target commit** — the newest commit in `<base>..HEAD` that last touched the
61
- file a fix applies to. Each fix is folded into its target commit.
62
-
63
- ## Safety and stop points
64
-
65
- These rules are mandatory:
66
-
67
- - Never rewrite history on `main` or `4.x`. Confirm the branch first with
68
- `git branch --show-current`.
69
- - Stop and ask the user whenever a thread requests a clarification or decision
70
- (Step 3). Do not guess on ambiguous feedback.
71
- - Force-push only with `--force-with-lease`, and only after the user confirms
72
- (Step 6).
73
- - Do not resolve a thread until its fix is committed and pushed (Step 7).
74
-
75
- ## Workflow
76
-
77
- 1. [Identify the PR and branch](#step-1-identify-the-pr-and-branch)
78
- 2. [Fetch unresolved review threads](#step-2-fetch-unresolved-review-threads)
79
- 3. [Triage each thread](#step-3-triage-each-thread) — ask for clarifications or
80
- decisions as needed
81
- 4. [Implement the changes](#step-4-implement-the-changes)
82
- 5. [Fold each change into the matching commit](#step-5-fold-each-change-into-the-matching-commit)
83
- 6. [Force-push the branch](#step-6-force-push-the-branch)
84
- 7. [Reply to and resolve threads](#step-7-reply-to-and-resolve-threads)
85
- 8. [Request another Copilot review](#step-8-request-another-copilot-review)
86
-
87
- ## Step 1: Identify the PR and branch
88
-
89
- Confirm the branch and locate the PR for it:
90
-
91
- ```bash
92
- git branch --show-current
93
- gh pr view --json number,title,headRefName,baseRefName,url,state
94
- ```
95
-
96
- Record the PR number, `baseRefName` (the base branch), and URL. If no PR is
97
- associated with the branch, stop and tell the user.
98
-
99
- ## Step 2: Fetch unresolved review threads
100
-
101
- List the first 100 review threads and keep the ones where `isResolved` is
102
- `false`. For unusually active PRs with more than 100 review threads, paginate
103
- before assuming no unresolved threads remain.
104
-
105
- ```bash
106
- OWNER=$(gh repo view --json owner --jq '.owner.login')
107
- REPO=$(gh repo view --json name --jq '.name')
108
- PR_NUMBER=$(gh pr view --json number --jq '.number')
109
-
110
- gh api graphql -f query='
111
- query($owner:String!, $repo:String!, $pr:Int!) {
112
- repository(owner:$owner, name:$repo) {
113
- pullRequest(number:$pr) {
114
- reviewThreads(first:100) {
115
- nodes {
116
- id
117
- isResolved
118
- isOutdated
119
- path
120
- line
121
- comments(first:30) {
122
- nodes { databaseId author { login } body }
123
- }
124
- }
125
- }
126
- }
127
- }
128
- }' -F owner="$OWNER" -F repo="$REPO" -F pr="$PR_NUMBER" \
129
- --jq '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false)'
130
- ```
131
-
132
- For each unresolved thread, note its `id` (thread ID, needed to resolve it), the
133
- first comment `databaseId` (needed to reply), the `path`, and the `line`.
134
-
135
- ## Step 3: Triage each thread
136
-
137
- For each unresolved thread, classify it and act:
138
-
139
- - **Actionable and unambiguous** → plan the concrete code or doc change.
140
- - **Needs a clarification or decision** → stop and ask the user. Present the
141
- thread's file, line, and comment text, and the specific question or the
142
- options you see. Wait for the answer before implementing.
143
- - **Not applicable / disagree** → do not change code; draft a short, respectful
144
- reply explaining why (used in Step 7). Ask the user if you are unsure whether
145
- to push back.
146
-
147
- Do not proceed to Step 4 for a thread until its resolution is clear.
148
-
149
- ## Step 4: Implement the changes
150
-
151
- Apply the agreed changes in the workspace. Keep edits for each thread minimal and
152
- scoped to what the feedback asks. If the project has tests or linters, run the
153
- relevant checks before folding changes into commits:
154
-
155
- ```bash
156
- bundle exec rake default
157
- ```
158
-
159
- Fix any failures before continuing.
160
-
161
- ## Step 5: Fold each change into the matching commit
162
-
163
- Amend each change into its target commit — the existing commit on this branch
164
- that last touched the file — instead of adding new follow-up commits.
165
-
166
- 1. Compute the base once:
167
-
168
- ```bash
169
- BASE=$(git merge-base origin/<base-branch> HEAD)
170
- ```
171
-
172
- 2. For each changed file, find its target commit (the topmost line is newest):
173
-
174
- ```bash
175
- git log --oneline "$BASE"..HEAD -- <path>
176
- ```
177
-
178
- 3. Stage that file and create a fixup commit aimed at its target SHA:
179
-
180
- ```bash
181
- git add <path>
182
- git commit --fixup=<target-sha>
183
- ```
184
-
185
- Repeat for each changed file. When several files share the same target
186
- commit, stage them together for one fixup.
187
-
188
- 4. Autosquash the fixups into their targets non-interactively:
189
-
190
- ```bash
191
- GIT_SEQUENCE_EDITOR=: git rebase -i --autosquash "$BASE"
192
- ```
193
-
194
- 5. Verify the result — the fixup commits should be gone and history should be
195
- clean:
196
-
197
- ```bash
198
- git --no-pager log --oneline "$BASE"..HEAD
199
- git status --short --branch
200
- ```
201
-
202
- If a change does not correspond to any existing commit (e.g. a brand-new file
203
- requested in review), ask the user whether to fold it into a related commit or
204
- add a new, conventionally formatted commit.
205
-
206
- ## Step 6: Force-push the branch
207
-
208
- History was rewritten, so the branch must be force-pushed. This is a
209
- history-rewriting operation — confirm with the user first, then use a lease to
210
- avoid clobbering unseen remote commits:
211
-
212
- ```bash
213
- git push --force-with-lease
214
- ```
215
-
216
- If the push is rejected, someone updated the remote branch. Fetch and reconcile
217
- before retrying; do not use `--force` to override the lease.
218
-
219
- ## Step 7: Reply to and resolve threads
220
-
221
- For each thread that is now addressed:
222
-
223
- 1. Reply to the thread, referencing what changed. Keep reply bodies shell-safe:
224
- use single quotes for simple one-line replies, or assign a quoted heredoc to a
225
- variable for arbitrary text. Do not put human-written reply text directly in a
226
- double-quoted shell argument; review comments can contain characters such as
227
- `!`, `$`, backticks, or quotes that the shell may expand before `gh` runs.
228
-
229
- ```bash
230
- COMMENT_DATABASE_ID=COMMENT_DATABASE_ID_FROM_THREAD
231
- reply_body='Addressed in the latest push: <short summary>.'
232
-
233
- gh api \
234
- "repos/$OWNER/$REPO/pulls/$PR_NUMBER/comments/$COMMENT_DATABASE_ID/replies" \
235
- -f body="$reply_body"
236
- ```
237
-
238
- For multi-line replies or text that may contain shell metacharacters, use a
239
- single-quoted heredoc delimiter:
240
-
241
- ```bash
242
- COMMENT_DATABASE_ID=COMMENT_DATABASE_ID_FROM_THREAD
243
- reply_body=$(cat <<'EOF'
244
- Addressed in the latest push: the guidance now covers `@!method` declarations.
245
- EOF
246
- )
247
-
248
- gh api \
249
- "repos/$OWNER/$REPO/pulls/$PR_NUMBER/comments/$COMMENT_DATABASE_ID/replies" \
250
- -f body="$reply_body"
251
- ```
252
-
253
- 2. Resolve the thread:
254
-
255
- ```bash
256
- gh api graphql -f query='
257
- mutation($threadId:ID!) {
258
- resolveReviewThread(input:{threadId:$threadId}) {
259
- thread { id isResolved }
260
- }
261
- }' -F threadId=THREAD_ID
262
- ```
263
-
264
- Only resolve threads whose feedback was actually addressed (or that the user
265
- agreed to close after a reply). Leave threads open when the user still owes a
266
- decision.
267
-
268
- ## Step 8: Request another Copilot review
269
-
270
- Request a fresh Copilot review on the PR so it re-reviews the amended commits.
271
-
272
- - Preferred: activate the pull request management tools, then request a Copilot
273
- review via the GitHub pull request tooling (`request_copilot_review`).
274
- - Do **not** create a new Copilot PR task for a re-review; that opens separate
275
- work instead of re-reviewing this PR.
276
-
277
- Finish by reporting to the user: the threads resolved, any threads left open and
278
- why, the new commit list, and the PR URL.
279
-
280
- ## Troubleshooting
281
-
282
- | Issue | Solution |
283
- | ----- | -------- |
284
- | `git log "$BASE"..HEAD -- <path>` is empty | The file is new on this branch; ask the user whether to fold into a related commit or add a new commit. |
285
- | Rebase stops with conflicts | Resolve the conflict, `git add` the files, then `git rebase --continue`. |
286
- | Force-push rejected despite `--force-with-lease` | The remote branch moved; run `git fetch`, review the remote changes, reconcile, and retry. |
287
- | A thread has no obvious file/line (`path` is null) | It is a PR-level comment; reply at the PR level and resolve only if addressed. |
288
- | Unsure whether to push back on feedback | Stop and ask the user before replying or resolving. |