Why interactive rebase
Interactive rebase rewrites a sequence of commits into a cleaner, more meaningful history before publishing. It is the surgical instrument of Git: you can reorder, edit, squash, fixup, drop, reword, or split commits, all in a single guided session. Mastering it transforms a messy local branch into a story reviewers can follow.
The todo list
Running git rebase -i opens an editor with a todo list. Each line has a verb and a commit. Reorder lines to reorder commits. Change verbs to change behavior.
git rebase -i HEAD~5
Verbs include pick (use commit), reword (edit message only), edit (stop to amend), squash (combine into previous, keep both messages), fixup (combine, discard message), drop (delete), and exec (run a shell command between commits). Two newer verbs are break (pause unconditionally) and label/reset/merge for the rebase merge graph (since Git 2.18).
Splitting a commit
Mark the commit with edit, then unwind and recommit:
git reset HEAD^
git add -p
git commit -m "First logical change"
git add -p
git commit -m "Second logical change"
git rebase --continue
Autosquash workflow
When you spot a typo in an earlier commit, create a fixup commit, then let rebase order them automatically:
git commit --fixup=<sha>
git rebase -i --autosquash HEAD~10
Set rebase.autoSquash = true in your config to make this the default. Pair with rebase.autoStash = true so dirty working trees do not block the rebase.
Exec for verification
Use exec lines to verify each commit builds and tests pass — invaluable for keeping a bisectable history:
git rebase -i --exec "cargo test" main
Every commit between HEAD and main will be checked out and the command run. If it fails, rebase pauses so you can fix and continue.
Rebase merges with --rebase-merges
Traditional rebase flattens merges. Pass --rebase-merges to preserve topology while still allowing reordering:
git rebase -i --rebase-merges main
Common mistakes
Rebasing published commits forces collaborators into history surgery. Reserve interactive rebase for branches you alone own, or coordinate explicitly. Forgetting to git rebase --continue after resolving conflicts leaves the rebase half-applied. Use git status — it tells you exactly what to do next. Finally, if you destroy work, git reflog almost always rescues it; see "Git internals: references and the reflog".
Recovery
If a rebase goes badly, abort and start fresh:
git rebase --abort
git reflog
git reset --hard HEAD@{5}
See also "Squashing and reorganizing commits" for higher-level patterns.