Interactive rebase is the feature I most wanted to internalise when I was learning git, and the one I had the most trouble teaching other people. So this is me doing the thing on a real-looking branch.
The branch has six commits. Three of them are mine being sloppy: initial cache impl, two typo commits, add cache metrics, fix tests (which should really have been folded into the metrics commit), and a WIP refactor cache layer that I want to reword into a proper message.
The todo list I write is the whole trick. pick the first real commit. squash the two typo commits into it (squash combines the message; fixup discards it). pick the metrics commit. fixup the fix-tests commit because its message is garbage. reword the WIP commit so I can write a real message.
Notice that rebase pauses twice: once to combine the squash messages, once to open the editor for the reword. The final git log --oneline -3 shows three clean commits where there used to be six.
Callouts:
squashvsfixup: squash opens the editor so you can merge messages. fixup keeps the earlier message and throws the later one away. I use fixup about 80% of the time.- This only rewrites local history. If you’ve pushed the branch, you’ll need
--force-with-leaseto replace the remote version. - I never rebase
main. Ever. Everything else is fair game.