Git interactive rebase: clean commits before review
A branch full of wip and typo commits is hard to review. Interactive rebase lets you squash, reorder and reword commits into a history that explains the change.
While you work, commits are save points: "wip", "fix typo", "try again". That is fine. Before a pull request, those save points are noise. A reviewer wants to read three clear steps, not eleven fragments.
Interactive rebase turns the first kind of history into the second.
Start an interactive rebase
To edit the last four commits:
git rebase -i HEAD~4
Git opens an editor with one line per commit, oldest first.
pick a1b2c3d Add discount field to cart
pick d4e5f6a wip
pick 0718293 Fix typo
pick 4a5b6c7 Add discount tests
Change the word at the start of a line to tell Git what to do with that commit.
| Command | Effect |
|---|---|
pick |
Keep the commit as it is |
reword |
Keep the changes, edit the message |
squash |
Merge into the commit above and combine the messages |
fixup |
Merge into the commit above and discard this message |
edit |
Stop here so you can change the commit |
drop |
Remove the commit |
You can also reorder lines to reorder commits.
pick a1b2c3d Add discount field to cart
fixup d4e5f6a wip
fixup 0718293 Fix typo
pick 4a5b6c7 Add discount tests
Save and close. Four commits become two that each mean something.
Mark fixups as you go
When you fix something that belongs to an earlier commit, say so at commit time:
git commit --fixup a1b2c3d
git rebase -i --autosquash main
Git places each fixup under its target automatically. You only confirm.
Update the remote branch safely
A rebase rewrites commits, so a normal push is rejected. Use:
git push --force-with-lease
Unlike --force, this refuses to overwrite the remote if someone else pushed in the meantime.
Rules that keep you out of trouble
- Rewrite only your own branch. Never rebase
mainor a branch other people build on. - Rebase before review, not during. Once reviewers have commented, add new commits so they can see what changed.
- You can always back out.
git rebase --abortstops a rebase in progress, andgit refloglists every earlier state of the branch if you need to return to one.
Stay current with main
The same command keeps a feature branch up to date without merge commits:
git fetch origin
git rebase origin/main
Why it is worth the minute
A clean history makes reviews faster, makes git bisect and git revert useful, and tells the next developer why each change was made. That includes you, six months from now.