Git Surgery
Perform git history operations safely. Every history rewrite must be planned, dry-run first, and executed only after explicit user approval.
Core rules
- NEVER rewrite history without a dry run first.
- NEVER use
git push --forceunless the user explicitly types the command themselves. - Always operate on a clean tree:
git status --porcelainmust be empty (or stash first). - Record the current HEAD before any operation:
git rev-parse HEAD— note it for the user. - After any rewrite, verify:
git log --oneline -5andgit status.
Common operations
Split a commit
git log --oneline -10— identify the commit to split.git rebase -i <commit>^and mark the commit asedit(or rungit reset --soft <commit>^).- Stage changes in logical chunks:
git add -p <file>orgit add <files>. - Commit each chunk with a focused message:
git commit -m "...". - When done:
git rebase --continueorgit statusto confirm clean. - Verify the final log reads cleanly.
Undo an unpushed commit (soft reset)
git reset --soft HEAD~1keeps changes staged;git reset --mixed HEAD~1keeps them unstaged. Confirm intent first: does the user want to keep the changes?
Cherry-pick
git log --oneline --all | head -20to find the target commit.git cherry-pick <sha>— expect conflicts; resolve withgit statusandgit add, thengit cherry-pick --continue.- To abort:
git cherry-pick --abort.
Revert (safe for pushed history)
git revert <sha>creates an inverse commit — the ONLY safe way to undo pushed history.
Squash last N commits
git rebase -i HEAD~N— set all but the first tosquash.- Preserve the first commit message as the summary; keep the body informative.
Conflict resolution protocol
git statusto enumerate conflicts.- For each conflicted file: show both sides (
git diff --cc <file>or open it). - Resolve deliberately — ask the user when semantics are ambiguous.
git addeach resolved file, then finish the operation.
Safety checklist (run before every rewrite)
- Working tree clean (or stashed)
- HEAD recorded
- Dry-run/plan shown to user
- User approved the exact commands
- No force-push unless user typed it themselves