| name | git-surgeon |
| description | Non-interactive hunk-level git staging, unstaging, discarding, undoing, fold, amend, squash, commit splitting, and commit reordering. Use when selectively staging, unstaging, discarding, reverting, squashing, splitting, or reordering individual diff hunks by ID instead of interactively. |
git-surgeon
CLI for hunk-level git operations without interactive prompts. Useful for AI
agents that need precise control over which changes to stage, unstage, discard,
or undo.
Commands
git-surgeon hunks
git-surgeon hunks --staged
git-surgeon hunks --file=src/main.rs
git-surgeon hunks --commit <HEAD/sha>
git-surgeon hunks --commit <sha> --full
git-surgeon hunks --blame
git-surgeon hunks --blame --staged
git-surgeon hunks --blame --commit <sha>
git-surgeon show <id>
git-surgeon show <id> --commit HEAD
git-surgeon stage <id1> <id2> ...
git-surgeon stage <id> --lines 5-30
git-surgeon commit <id1> <id2> ... -m "message"
git-surgeon commit <id>:1-11 <id2> -m "message"
git-surgeon commit-to <branch> <id1> <id2> ... -m "message"
git-surgeon commit-to main <id>:1-11 <id2> -m "message"
git-surgeon unstage <id1> <id2> ...
git-surgeon unstage <id> --lines 5-30
git-surgeon discard <id1> <id2> ...
git-surgeon discard <id> --lines 5-30
git-surgeon fold <target>
git-surgeon fold <target> --from <commit>
git-surgeon fold <target> --from <commit1> <commit2> <commit3>
git-surgeon amend <commit>
git-surgeon reword HEAD -m "new message"
git-surgeon reword <commit> -m "new message"
git-surgeon reword HEAD -m "subject" -m "body"
git-surgeon squash HEAD~1 -m "combined feature"
git-surgeon squash HEAD~2 -m "Add user auth" -m "Implements JWT-based authentication."
git-surgeon squash <commit> -m "feature complete"
git-surgeon squash HEAD~3 --force -m "squash with merges"
git-surgeon squash HEAD~1 --no-preserve-author -m "use current author"
git-surgeon undo <id1> <id2> ... --from <commit>
git-surgeon undo <id> --from <commit> --lines 2-10
git-surgeon undo-file <file1> <file2> ... --from <commit>
git-surgeon split HEAD \
--pick <id1> <id2> -m "first commit" \
--rest-message "remaining changes"
git-surgeon split HEAD \
--pick <id1> -m "Add feature" -m "Detailed description here." \
--rest-message "Other changes" --rest-message "Body for rest."
git-surgeon split <commit> \
--pick <id>:1-11,20-30 <id2> -m "partial split"
git-surgeon move <sha> --after <target-sha>
git-surgeon move <sha> --before <target-sha>
git-surgeon move <sha> --to-end
git-surgeon update
git-surgeon split HEAD \
--pick <id1> -m "first" \
--pick <id2> -m "second" \
--rest-message "rest"
Typical workflow
- Run
git-surgeon hunks to list hunks with their IDs
- Use
git-surgeon show <id> to inspect a hunk (lines are numbered)
- Stage and commit in one step:
git-surgeon commit <id1> <id2> -m "message"
- Or stage separately:
git-surgeon stage <id1> <id2>, then git commit
- To commit only part of a hunk, use inline ranges:
git-surgeon commit <id>:5-30 -m "message"
Committing to another branch
Use commit-to when working in a worktree and you need to commit changes to a
branch checked out elsewhere (e.g., main):
- Run
git-surgeon hunks to list hunks
- Commit to another branch:
git-surgeon commit-to main <id1> <id2> -m "message"
- The hunks are applied to the target branch's tree and discarded from the working tree
- Fails if the patch cannot be applied cleanly to the target branch
Picking the right folding command
| You have... | Use |
|---|
| Staged changes | git-surgeon amend <target> |
| One existing commit, defaulting to HEAD | git-surgeon fold <target> |
| One or more named commits | git-surgeon fold <target> --from <sha> |
Folding existing commits into earlier commits
fold folds one or more existing commits into an earlier one. The source(s)
(default: HEAD) are removed from history and their changes merge into the
target. Intermediate commits stay untouched. Dirty working tree is autostashed.
Refuses to run when the index already has staged changes.
git-surgeon fold <target> -- fold HEAD into target (most common)
git-surgeon fold <target> --from <commit> -- fold a specific non-HEAD commit
git-surgeon fold <target> --from <c1> <c2> <c3> -- fold multiple commits in one pass
- Fails if the range contains merge commits
Using --blame to find the fold target
Use --blame to see which commit introduced the surrounding lines:
git-surgeon hunks --blame
Output shows commit hashes for each line:
a1b2c3d src/auth.rs (+2 -0)
8922b52 fn login(user: &str) {
8922b52 validate(user);
0000000 + log_attempt(user); # new line, not yet committed
0000000 + audit(user); # new line, not yet committed
8922b52 }
The context lines show 8922b52 -- that's the commit where this function was
added. If your new lines belong with that change:
git-surgeon commit a1b2c3d -m "add login logging"
git-surgeon fold 8922b52
Amending earlier commits with staged changes
amend folds staged changes into an earlier commit. For HEAD, amends directly;
for older commits, uses autosquash rebase. Unstaged changes are preserved. For
folding an existing commit instead, use fold.
- Stage desired hunks:
git-surgeon stage <id1> <id2>
- Amend the target commit:
git-surgeon amend <commit-sha>
Squashing commits
Squash collapses ALL commits from the target through HEAD into one, including
any unrelated commits in that range. Preview with git log <target>..HEAD --oneline first. If the range is mixed, use fold --from <c1> <c2> ... to
fold only named commits, or move --to-end the unrelated ones first.
- Squash commits from a target commit through HEAD:
git-surgeon squash HEAD~2 -m "combined"
- Use multiple
-m flags for subject + body: git-surgeon squash HEAD~1 -m "Subject" -m "Body paragraph"
- Target commit must be an ancestor of HEAD
- Use
--force to squash ranges containing merge commits
- Uncommitted changes are autostashed and restored
- Author from the oldest commit is preserved by default; use
--no-preserve-author for current user
Undoing changes from commits
- Run
git-surgeon hunks --commit <sha> to list hunks in a commit
- Undo specific hunks:
git-surgeon undo <id> --from <sha>
- Or undo entire files:
git-surgeon undo-file src/main.rs --from <sha>
- Changes appear as unstaged modifications in the working tree
Splitting commits
- List hunks in the commit:
git-surgeon hunks --commit <sha>
- For small commits, use
--full to see all lines with line numbers in one call
- Split by picking hunks:
git-surgeon split <sha> --pick <id1> -m "first" --rest-message "second"
- Use multiple
-m flags for subject + body: --pick <id> -m "Subject" -m "Body paragraph"
- Use
id:range syntax for partial hunks: --pick <id>:5-20
- For non-contiguous lines, use commas:
--pick <id>:2-6,34-37
- Works on HEAD (direct reset) or earlier commits (via rebase)
- Requires a clean working tree
Moving commits
move reorders commits in history. Useful for grouping related changes or
moving a commit to a logical position after splitting.
git-surgeon move <sha> --after <target> -- place commit right after target
git-surgeon move <sha> --before <target> -- place commit right before target
git-surgeon move <sha> --to-end -- place commit at HEAD
- Dirty working tree is autostashed
- Fails if the range contains merge commits
Hunk IDs
- 7-character hex strings derived from file path + hunk content
- Stable across runs as long as the diff content hasn't changed
- Duplicates get
-2, -3 suffixes
- If a hunk ID is not found, re-run
hunks to get fresh IDs