From f20da58fa05bec82e59d79aacd09f12b18819e43 Mon Sep 17 00:00:00 2001 From: Andrew Horn Date: Mon, 20 Apr 2026 10:03:32 -0700 Subject: [PATCH 1/6] feat: add intelligent conflict resolution to rebase skill Replace the abort-on-conflict behavior with a step-by-step conflict resolution workflow: identify conflicted files, auto-resolve clear cases (imports, generated files, whitespace), ask the user on ambiguous logic changes, and report all resolutions. Add recovery step and explicit rules for safe rebase behavior. Co-Authored-By: Claude Opus 4.6 (1M context) --- skills/rebase/SKILL.md | 82 +++++++++++++++++++++++++++++++++++------- 1 file changed, 69 insertions(+), 13 deletions(-) diff --git a/skills/rebase/SKILL.md b/skills/rebase/SKILL.md index 863e131..8c7c1e2 100644 --- a/skills/rebase/SKILL.md +++ b/skills/rebase/SKILL.md @@ -69,36 +69,92 @@ If they match, the branch is already up-to-date. Inform the user and stop. git rebase origin/ ``` -### On success +### Clean rebase (no conflicts) -Report how many commits ahead of the base branch: +Report success briefly: + +- How many commits were replayed (`git rev-list --count origin/..HEAD`) +- The branch is now up to date with `origin/` +- If the branch was previously pushed, mention that a force-push (`git push --force-with-lease`) will be needed to update the remote — but do NOT push automatically + +If changes were stashed in Step 1, restore them with `git stash pop`. If stash pop fails due to conflicts, inform the user and suggest `git stash show` to review the stashed changes. + +## Step 4: Handling conflicts + +When `git rebase` stops with conflicts: + +### 4a. Identify conflicted files ```bash -git rev-list --count origin/..HEAD +git diff --name-only --diff-filter=U ``` -### On conflict +### 4b. Resolve each conflicted file + +Read the full file content and locate conflict markers (`<<<<<<<`, `=======`, `>>>>>>>`). For each conflict chunk, decide: + +**Auto-resolve** (the right answer is clear): -Abort the rebase: +- Both sides added imports or list items — combine both sets, deduplicate, maintain sort order +- Generated files (`.g.dart`, `.freezed.dart`, `.gen.dart`, lock files) — take the current branch version; note that regeneration is needed after rebase completes +- Formatting / whitespace-only diffs — accept either side +- One side added new code, the other didn't touch that region — take the addition +- One side modified code the other side deleted — prefer the modification, but mention it in the summary so the user can verify the deletion wasn't intentional + +**Stop and ask the user** (the right answer requires judgment): + +- Both sides changed the same function or logic block differently +- Business logic where correctness depends on product intent +- Anything you aren't confident about + +When in doubt, ask. Losing someone's work is far worse than pausing to check. + +After resolving all conflicts in a file, write the clean version and stage it: ```bash -git rebase --abort +git add ``` -If changes were stashed in Step 1, restore them with `git stash pop`. +### 4c. Continue the rebase -Inform the user that the rebase had conflicts and suggest resolving manually: +```bash +git rebase --continue +``` + +Multi-commit rebases may produce conflicts at multiple steps. Repeat 4a-4c for each. + +### 4d. After all conflicts are resolved, report + +- Every conflict that was resolved, with a one-line explanation of what you chose +- Any files flagged for regeneration +- Suggest running the project's build/test/format/analyze commands to verify correctness +- If the branch was previously pushed, mention that a force-push (`git push --force-with-lease`) will be needed — but do NOT push automatically + +If changes were stashed in Step 1, restore them with `git stash pop`. If `stash pop` fails due to conflicts, inform the user and suggest `git stash show` to review the stashed changes. + +## Step 5: Recovery + +If the rebase enters a bad state or a conflict is too ambiguous to resolve safely: -> Automatic rebase failed due to conflicts. To resolve manually, run: `git rebase origin/` +```bash +git rebase --abort +``` + +This restores the branch to its exact pre-rebase state — nothing is lost. Explain what went wrong so the user can decide how to proceed. + +If changes were stashed in Step 1, restore them with `git stash pop`. ## Gotchas -- If the branch has already been pushed to a remote, rebasing rewrites history. The user will need to force-push (`git push --force-with-lease`) after a successful rebase — warn them. -- `git stash pop` can itself cause conflicts if stashed changes overlap with rebased commits. If stash pop fails, inform the user and suggest `git stash show` to review the stashed changes. - Detached HEAD state (`HEAD` instead of a branch name) means the user is not on any branch. Inform them and stop — do not attempt to rebase. - If the base branch does not exist locally but does on the remote, `git fetch` in Step 2 will create the remote tracking ref. The rebase uses `origin/`, not the local branch. -## Important +## Rules -- This skill only manages git state. Do not modify project files. +- Never force-push unless the user explicitly asks. +- Never squash, reorder, or edit commits during the rebase — just replay them. +- Never proceed on a dirty working tree without the user's consent. +- Prefer keeping both sides' changes when combining — err on the side of inclusion. +- After resolving conflicts, always recommend running build, test, format, and analyze to verify. +- This skill only manages git state. Do not modify project files outside of conflict resolution. - If changes were stashed, always restore them — even if the rebase fails. From 6175ec6e7a52774aa1c54e3caad2324b266db772 Mon Sep 17 00:00:00 2001 From: Andrew Horn Date: Thu, 11 Jun 2026 08:55:04 -0700 Subject: [PATCH 2/6] docs: keep rebase conflict guidance tech-agnostic Replace Dart-specific generated file extensions with a general description of generated and lock files. Co-Authored-By: Claude Opus 4.8 --- skills/rebase/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skills/rebase/SKILL.md b/skills/rebase/SKILL.md index 8c7c1e2..574f671 100644 --- a/skills/rebase/SKILL.md +++ b/skills/rebase/SKILL.md @@ -96,7 +96,7 @@ Read the full file content and locate conflict markers (`<<<<<<<`, `=======`, `> **Auto-resolve** (the right answer is clear): - Both sides added imports or list items — combine both sets, deduplicate, maintain sort order -- Generated files (`.g.dart`, `.freezed.dart`, `.gen.dart`, lock files) — take the current branch version; note that regeneration is needed after rebase completes +- Generated or lock files (anything produced by a build step or dependency resolver rather than edited by hand) — take the current branch version; note that regeneration is needed after rebase completes - Formatting / whitespace-only diffs — accept either side - One side added new code, the other didn't touch that region — take the addition - One side modified code the other side deleted — prefer the modification, but mention it in the summary so the user can verify the deletion wasn't intentional From 7750bd43eb12b8747fc50ea2e290f350ba7825ee Mon Sep 17 00:00:00 2001 From: Andrew Horn Date: Thu, 11 Jun 2026 08:58:31 -0700 Subject: [PATCH 3/6] feat: allow safe read-only git commands in rebase skill Pre-approve the read-only git queries the rebase skill runs (rev-parse, rev-list, status, merge-base, diff) plus git add, so conflict resolution isn't interrupted by permission prompts for safe commands. Co-Authored-By: Claude Opus 4.8 --- skills/rebase/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skills/rebase/SKILL.md b/skills/rebase/SKILL.md index 574f671..164586c 100644 --- a/skills/rebase/SKILL.md +++ b/skills/rebase/SKILL.md @@ -4,7 +4,7 @@ user-invocable: true disable-model-invocation: true description: Rebases the current feature branch onto the base branch (main/master/develop). when_to_use: Use when user says "rebase", "sync branch", or "update branch". -allowed-tools: Bash(*/scripts/detect-base-branch.sh) Bash(git fetch *) Bash(git rebase *) Bash(git stash *) +allowed-tools: Bash(*/scripts/detect-base-branch.sh) Bash(git fetch *) Bash(git rebase *) Bash(git stash *) Bash(git rev-parse *) Bash(git rev-list *) Bash(git status *) Bash(git merge-base *) Bash(git diff *) Bash(git add *) effort: low compatibility: Designed for Claude Code (or similar products with git access) --- From 4bd167be09564cf008f9925f0ebfdf9a8468362a Mon Sep 17 00:00:00 2001 From: Andrew Horn Date: Thu, 11 Jun 2026 09:16:39 -0700 Subject: [PATCH 4/6] fix: enable and harden the rebase skill conflict-resolution path Grant the Read and Edit tools the conflict-resolution step needs to read and rewrite conflicted files, and add a GIT_EDITOR=true allowlist entry. Run `git rebase --continue` with GIT_EDITOR=true so a commit-message editor cannot hang the agent, and stop-and-report on non-conflict failures (e.g. a pre-commit hook) instead of looping. Generalize the post-resolution verify wording, rename "Step 5: Recovery" to a conditional "Recovery (if needed)" heading, and bump effort to medium. Co-Authored-By: Claude Opus 4.8 --- skills/rebase/SKILL.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/skills/rebase/SKILL.md b/skills/rebase/SKILL.md index 164586c..a45aa60 100644 --- a/skills/rebase/SKILL.md +++ b/skills/rebase/SKILL.md @@ -4,8 +4,8 @@ user-invocable: true disable-model-invocation: true description: Rebases the current feature branch onto the base branch (main/master/develop). when_to_use: Use when user says "rebase", "sync branch", or "update branch". -allowed-tools: Bash(*/scripts/detect-base-branch.sh) Bash(git fetch *) Bash(git rebase *) Bash(git stash *) Bash(git rev-parse *) Bash(git rev-list *) Bash(git status *) Bash(git merge-base *) Bash(git diff *) Bash(git add *) -effort: low +allowed-tools: Bash(*/scripts/detect-base-branch.sh) Bash(git fetch *) Bash(git rebase *) Bash(GIT_EDITOR=true git rebase *) Bash(git stash *) Bash(git rev-parse *) Bash(git rev-list *) Bash(git status *) Bash(git merge-base *) Bash(git diff *) Bash(git add *) Read Edit +effort: medium compatibility: Designed for Claude Code (or similar products with git access) --- @@ -118,21 +118,23 @@ git add ### 4c. Continue the rebase ```bash -git rebase --continue +GIT_EDITOR=true git rebase --continue ``` -Multi-commit rebases may produce conflicts at multiple steps. Repeat 4a-4c for each. +`GIT_EDITOR=true` stops `git` from opening an interactive editor for the commit message, which would otherwise hang with no terminal attached. + +Multi-commit rebases may produce conflicts at multiple steps. Repeat 4a-4c for each. If `git rebase --continue` fails for a reason other than conflicts — for example, a pre-commit hook rejects the commit — stop and report the failure rather than looping. ### 4d. After all conflicts are resolved, report - Every conflict that was resolved, with a one-line explanation of what you chose - Any files flagged for regeneration -- Suggest running the project's build/test/format/analyze commands to verify correctness +- Suggest running the project's own build, test, and format/lint checks to verify correctness - If the branch was previously pushed, mention that a force-push (`git push --force-with-lease`) will be needed — but do NOT push automatically If changes were stashed in Step 1, restore them with `git stash pop`. If `stash pop` fails due to conflicts, inform the user and suggest `git stash show` to review the stashed changes. -## Step 5: Recovery +## Recovery (if needed) If the rebase enters a bad state or a conflict is too ambiguous to resolve safely: From dc9f764e61fd77c4f4b0b23b66c3158dbe539593 Mon Sep 17 00:00:00 2001 From: Andrew Horn Date: Thu, 11 Jun 2026 09:17:02 -0700 Subject: [PATCH 5/6] fix: make rebase conflict-resolution heuristics safer Reword generated/lock-file resolution to resolve by content and warn that --ours/--theirs are reversed during a rebase, avoiding accidental loss of upstream changes. Require explicit user confirmation when one side modified code the other deleted, since auto-keeping resurrects a file the other side intentionally removed. Drop the redundant low-confidence bullet already covered by "When in doubt, ask." Co-Authored-By: Claude Opus 4.8 --- skills/rebase/SKILL.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/skills/rebase/SKILL.md b/skills/rebase/SKILL.md index a45aa60..f7c7ce5 100644 --- a/skills/rebase/SKILL.md +++ b/skills/rebase/SKILL.md @@ -96,16 +96,15 @@ Read the full file content and locate conflict markers (`<<<<<<<`, `=======`, `> **Auto-resolve** (the right answer is clear): - Both sides added imports or list items — combine both sets, deduplicate, maintain sort order -- Generated or lock files (anything produced by a build step or dependency resolver rather than edited by hand) — take the current branch version; note that regeneration is needed after rebase completes +- Generated or lock files (anything produced by a build step or dependency resolver rather than edited by hand) — keep your feature branch's version (the change being replayed), then note that regeneration is needed after the rebase completes. Caution: during a rebase `--ours` is the base branch and `--theirs` is your commit — the reverse of a merge — so resolve by reading the content, not by reaching for `--ours`/`--theirs`. - Formatting / whitespace-only diffs — accept either side - One side added new code, the other didn't touch that region — take the addition -- One side modified code the other side deleted — prefer the modification, but mention it in the summary so the user can verify the deletion wasn't intentional +- One side modified code the other side deleted — prefer the modification, but call this out prominently in the summary and ask the user to confirm the deletion wasn't intentional, since keeping the change resurrects a file the other side removed **Stop and ask the user** (the right answer requires judgment): - Both sides changed the same function or logic block differently - Business logic where correctness depends on product intent -- Anything you aren't confident about When in doubt, ask. Losing someone's work is far worse than pausing to check. From aead8edc99187b5623ce39c449fcf64bf22fab63 Mon Sep 17 00:00:00 2001 From: Andrew Horn Date: Thu, 11 Jun 2026 09:17:16 -0700 Subject: [PATCH 6/6] docs: tidy rebase skill clean-path guidance and rules Suggest running the project's checks after a clean rebase too, since a clean rebase can still introduce semantic conflicts, and dedupe the stash-pop guidance by pointing the clean path at Step 4d. Generalize the verify wording away from a Dart/Flutter-flavored gate, add a rule to stage only resolved files (never git add -A), and rewrite the scope statement so it no longer contradicts the conflict-resolution edits. Co-Authored-By: Claude Opus 4.8 --- skills/rebase/SKILL.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/skills/rebase/SKILL.md b/skills/rebase/SKILL.md index f7c7ce5..a6d1f6c 100644 --- a/skills/rebase/SKILL.md +++ b/skills/rebase/SKILL.md @@ -75,9 +75,10 @@ Report success briefly: - How many commits were replayed (`git rev-list --count origin/..HEAD`) - The branch is now up to date with `origin/` +- Suggest running the project's own build, test, and format/lint checks — a clean rebase can still introduce semantic conflicts - If the branch was previously pushed, mention that a force-push (`git push --force-with-lease`) will be needed to update the remote — but do NOT push automatically -If changes were stashed in Step 1, restore them with `git stash pop`. If stash pop fails due to conflicts, inform the user and suggest `git stash show` to review the stashed changes. +If changes were stashed in Step 1, restore them with `git stash pop` (see Step 4d if the pop conflicts). ## Step 4: Handling conflicts @@ -156,6 +157,7 @@ If changes were stashed in Step 1, restore them with `git stash pop`. - Never squash, reorder, or edit commits during the rebase — just replay them. - Never proceed on a dirty working tree without the user's consent. - Prefer keeping both sides' changes when combining — err on the side of inclusion. -- After resolving conflicts, always recommend running build, test, format, and analyze to verify. -- This skill only manages git state. Do not modify project files outside of conflict resolution. +- Stage only the files you resolved — never `git add -A`. +- After resolving conflicts, always recommend running the project's own build, test, and format/lint checks to verify. +- Modify project files only to resolve rebase conflicts — make no other code changes. - If changes were stashed, always restore them — even if the rebase fails.