SKILL.md

  1---
  2name: rebasing-with-git
  3description: Guides git rebase workflows including simple rebases and complex fork rebases with drop-and-repick for personal integration branches. Use when the user asks to rebase, mentions rebasing, needs help with rebase conflicts, or asks to pull feature branch changes into a personal branch. Supports branch-based repos, worktrees, and wt-managed bare repos.
  4license: GPL-3.0-or-later
  5metadata:
  6  author: Amolith <amolith@secluded.site>
  7---
  8
  9## General principles
 10
 11- **Non-interactive rebases**: prefix with `GIT_EDITOR=true`. For interactive rebases that edit the todo, also set `GIT_SEQUENCE_EDITOR` (see [drop-and-repick](#step-5-rebase-with-drops-and-break)).
 12- **Never push** unless the user explicitly says to. If they say "force push", use `--force-with-lease`. Do not suggest pushing. When work is complete, stop.
 13- **Dirty worktree**: if uncommitted changes exist when a rebase is requested, ask the user how to proceed before doing anything.
 14- **In-progress rebase**: if `.git/rebase-merge` or `.git/rebase-apply` exists (or the worktree-local equivalents under `.git/worktrees/<name>/`), read the state—conflicts, staged changes, progress through the todo—and offer to continue or abort based on what you find.
 15- **rerere**: the user has `rerere` enabled. If a conflict is auto-resolved by rerere, note this to the user and verify the auto-resolution looks correct before continuing.
 16- **Checks**: read the project's `agents.md` for build/lint/format/test commands. Run format, lint, and typecheck after each logical step. Run the full test suite only at the end of the entire operation.
 17
 18## Repo layout detection
 19
 20Before starting, determine the layout:
 21
 221. **wt-managed bare repo**: `../.bare` is a directory. Worktrees are siblings of `.bare/`. Use `wt l` to list worktrees, `cd ../branch-name` to navigate. Add: `wt a name -b`. Remove: `wt r name -b`. If `wt` is not installed, fall back to `git worktree` commands.
 23
 242. **Legacy worktree layout**: `git worktree list` shows multiple entries but `../.bare` does not exist. Worktrees are sibling directories. Navigate with `cd ../name`. Use `git worktree add`/`remove`.
 25
 263. **Branch-based**: a normal clone with a single worktree. Use `git switch` to change branches.
 27
 28## Upstream remote and canonical branch
 29
 30For contributed-to projects, the upstream remote is named `upstream`. For the user's own projects, inspect `git remote -v` to identify the hosting remote.
 31
 32Determine the canonical branch:
 33
 34```sh
 35git symbolic-ref refs/remotes/<remote>/HEAD | sed 's|refs/remotes/<remote>/||'
 36```
 37
 38Fallback if the ref is not set:
 39
 40```sh
 41git remote show <remote> | grep 'HEAD branch' | sed 's/.*: //'
 42```
 43
 44## Simple rebase
 45
 461. `git fetch <remote>`
 472. `GIT_EDITOR=true git rebase <remote>/<canonical>`
 483. Handle conflicts if they arise (see [Handling conflicts](#handling-conflicts)).
 494. Run checks. Stop.
 50
 51## Handling conflicts
 52
 531. **Stop immediately.** Do not resolve without user confirmation. **Never skip a commit.** If a commit seems too complex to resolve, present what you see and ask the user—they may know the exact resolution.
 542. Run `git status` and examine every conflicting file thoroughly.
 553. Present to the user:
 56   - What the local changes are doing and why they were made
 57   - What the incoming changes are doing and why
 58   - Why the two sides conflict
 59   - Possible resolution strategies, with a light recommendation and brief reasoning for the recommended approach
 604. **Wait for the user to confirm or direct** a resolution.
 615. After resolving: `git add` the resolved files, then `GIT_EDITOR=true git rebase --continue`.
 62
 63### Bulk mechanical changes (import renames, formatting, etc.)
 64
 65Large-scale rename or formatting commits often produce massive conflict diffs that obscure the actual change. The typical resolution pattern is:
 66
 671. Check out HEAD's version of the affected files: `git checkout HEAD -- <paths>`
 682. Re-apply the mechanical transformation (e.g. `fd <pattern> -x sd '<old>' '<new>'`)
 693. Run the project's formatter
 704. `git add` and continue
 71
 72**Do not attempt to hand-resolve hundreds of conflicting hunks.** Recognize when a commit is mechanical in nature, describe it to the user, and ask how they want to re-apply the transformation.
 73
 74## Fork rebase: feature branches
 75
 76The user will already be in the correct worktree or have the branch checked out. Rebase only the current branch.
 77
 781. `git fetch upstream`
 792. Check divergence: `git log --oneline upstream/<canonical>..HEAD`
 803. `GIT_EDITOR=true git rebase upstream/<canonical>`
 814. Resolve conflicts per [Handling conflicts](#handling-conflicts).
 825. Run format/lint/typecheck.
 836. **Stop and wait.** The user may want to test manually, push, or move on.
 84
 85## Fork rebase: drop-and-repick (personal branch)
 86
 87This workflow is **always explicitly requested** by the user (e.g. "rebase on main, then pull changes back from feature branches"). The current branch/worktree is the personal branch.
 88
 89**Do not start the rebase immediately.** Analyze and confirm first.
 90
 91### Step 1: Verify feature branches are rebased
 92
 93For each local feature branch (exclude the canonical branch and the current personal branch), check whether it has already been rebased onto upstream:
 94
 95```sh
 96git log --oneline upstream/<canonical>..<branch>
 97```
 98
 99If any feature branch appears to need rebasing, warn the user or remind them to do it first.
100
101To enumerate branches: use `wt l` or `git worktree list` in worktree layouts, `git branch` in branch-based layouts.
102
103### Step 2: Examine the personal branch
104
105```sh
106git log --oneline upstream/<canonical>..HEAD
107```
108
109### Step 3: Correlate personal commits to feature branches
110
111For each feature branch, find its commits beyond upstream:
112
113```sh
114git log --oneline --reverse upstream/<canonical>..<branch>
115```
116
117The **oldest** commit's subject line identifies the feature branch in the personal branch. Search the personal branch log for a commit with the same subject. If found, that personal commit is a squashed (fixup'd) representation of the entire feature branch and should be dropped during rebase, then the feature branch re-picked fresh.
118
119**Only** branches with at least one commit ahead of upstream whose subject matches a commit in the personal branch should be included. Branches with no matching commit in personal are not represented there and should be ignored unless the user explicitly says to include new ones.
120
121If matches are ambiguous (e.g. multiple commits with very similar subjects across branches), flag this to the user before proceeding.
122
123Commits in the personal branch that match no feature branch are personal-only customizations. They stay.
124
125### Step 4: Present the plan
126
127Show the user:
128
129- **Commits to drop**: hash, subject, which feature branch they correspond to
130- **Commits to keep**: hash, subject (personal-only customizations)
131- **Feature branches to re-pick**: branch name, commit count, planned re-pick order
132
133Preserve the order the feature-branch commits originally appeared in the personal branch. Consistent ordering lets rerere help with any previously-resolved conflicts.
134
135**Wait for explicit confirmation before proceeding.**
136
137### Step 5: Rebase with drops and break
138
139The rebase todo must be structured as: **drop → break → pick**. The drops remove stale feature-branch commits, the break pauses the rebase so fresh cherry-picks can be inserted, and the remaining picks replay personal-only commits on top.
140
141Build a sed command that:
1421. Changes `pick` to `drop` for each identified commit
1432. Inserts a `break` line after the last `drop`, before the first remaining `pick`
144
145Use short hashes from `git log --oneline`; these match the abbreviation the rebase todo uses.
146
147```sh
148GIT_EDITOR=true \
149GIT_SEQUENCE_EDITOR="sed -i \
150  -e 's/^pick <hash1>/drop <hash1>/' \
151  -e 's/^pick <hash2>/drop <hash2>/' \
152  -e '/^drop <hash2>/a break'" \
153  git rebase -i upstream/<canonical>
154```
155
156Where `<hash2>` is the last commit being dropped (use `/a break` to append after it). If drops are non-contiguous in the todo, insert the break after the last one.
157
158The rebase will process the drops, then pause at the `break`. If personal-only commits conflict during the rebase (before or after the break), handle per [Handling conflicts](#handling-conflicts).
159
160### Step 6: Re-pick from feature branches (during break)
161
162The rebase is paused. Cherry-pick feature branches back in now, before the personal-only commits are replayed.
163
164For each feature branch, in the order confirmed in step 4:
165
1661. Get commits oldest-first:
167   ```sh
168   git log --oneline --reverse upstream/<canonical>..<branch>
169   ```
170
1712. **If the branch has a single commit**, cherry-pick it:
172   ```sh
173   git cherry-pick <hash>
174   ```
175
1763. **If the branch has multiple commits**, cherry-pick the first, then fixup the rest:
177   ```sh
178   git cherry-pick <first-hash>
179   git cherry-pick --no-commit <second-hash>
180   git commit --amend --no-edit
181   git cherry-pick --no-commit <third-hash>
182   git commit --amend --no-edit
183   ```
184   Continue for all remaining commits.
185
1864. **If `cherry-pick --no-commit` hits a conflict**: resolve per [Handling conflicts](#handling-conflicts), `git add` resolved files, then `git cherry-pick --quit` to clear the cherry-pick state while preserving staged changes, then `git commit --amend --no-edit`.
187
1885. Run format/lint/typecheck after completing each feature branch's re-pick.
189
190### Step 7: Continue the rebase
191
192After all feature branches are re-picked:
193
194```sh
195GIT_EDITOR=true git rebase --continue
196```
197
198This replays the personal-only commits on top of the freshly cherry-picked feature work. Handle conflicts per [Handling conflicts](#handling-conflicts).
199
200### Step 8: Final verification
201
2021. Review the log:
203   ```sh
204   git log --oneline upstream/<canonical>..HEAD
205   ```
206   Confirm the expected structure: personal-only commits and one squashed commit per re-picked feature branch, in the expected order.
207
2082. Run the full test suite.
209
2103. **Stop and wait.**