Learning Objectives
By the end of this lesson you will be able to:
- Open an interactive rebase over a chosen range of commits
- Read the todo list correctly, including its inverted order
- Name the six commands available on each line
- Choose the right range without accidentally including commits you did not write
What "Interactive" Adds
An ordinary rebase replays your commits onto a new base and asks you nothing. An interactive rebase replays them too — but first it shows you the list and lets you edit it.
That list is a plan. You change the plan, save the file, close the editor, and Git carries it out.
git rebase -i HEAD~4
Your editor opens with something like this:
pick 1a77c60 wip
pick 9d3e072 fix
pick 4c1f8ab fix the fix
pick 7b2e551 test: add PAY-4417 boundary cases
# Rebase e2b90d1..7b2e551 onto e2b90d1 (4 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# d, drop <commit> = remove commit
Every line is one commit, and the word at the front is what to do with it. Change nothing and save, and the rebase is a no-op — which makes opening the list to look completely safe.
The Order Trap
The todo list is oldest first. git log is newest first. They are opposite, and this is the single most common mistake in the whole module.
git log --oneline git rebase -i HEAD~4
7b2e551 test: boundary cases pick 1a77c60 wip ← oldest
4c1f8ab fix the fix pick 9d3e072 fix
9d3e072 fix pick 4c1f8ab fix the fix
1a77c60 wip pick 7b2e551 test: boundary… ← newest
The order in the todo list is the order the commits will be replayed, which has to be oldest first — you cannot replay a commit before its parent exists. Read it top to bottom as "and then, and then".
This matters most for squash and fixup, which merge a commit into the one above it in the list. Above means older. Getting this backwards squashes the wrong pair, which is the subject of the next lesson.
Choosing the Range
HEAD~4 means "the last four commits". That is fine when you know the number, but there is a better way to say what you actually mean:
git rebase -i main
This makes the todo list contain exactly the commits on your branch that are not on main — which is almost always the set you want to clean up.
Confirm it before you start, the same check as in the previous module:
git log --oneline main..HEAD
7b2e551 test: add PAY-4417 boundary cases
4c1f8ab fix the fix
9d3e072 fix
1a77c60 wip
Four commits, all yours. That is the list you are about to rewrite, and nothing outside it is touched.
Pro Tip: Prefer
git rebase -i maintogit rebase -i HEAD~n. Counting commits by hand is how people accidentally include a commit frommainin the range — and rewriting a commit that is onmainbreaks the Golden Rule as thoroughly as anything can.
The Six Commands
| Command | Effect |
|---|---|
pick |
Keep the commit as it is |
reword |
Keep the changes, open the editor to change the message |
edit |
Stop at this commit so you can amend or split it |
squash |
Merge into the commit above, combining both messages |
fixup |
Merge into the commit above, discarding this message |
drop |
Remove the commit and its changes entirely |
You can also reorder the lines, and deleting a line is identical to drop.
The next two lessons cover these in earnest. For now, the shape is what matters: you are writing a small program, one instruction per commit, and Git runs it from top to bottom.
What Happens When You Save
Git closes the editor and starts replaying. If every line was pick, it finishes instantly. If a line said reword, it stops and opens the message editor. If a line said edit, it stops and hands you a shell. If a replay conflicts, it stops with the conflict.
In all of those cases the state is the same one you already know from a plain rebase:
git rebase --continue # proceed after resolving or amending
git rebase --abort # give up, restore the branch exactly as it was
git rebase --skip # discard the commit currently being applied
And exactly as before: do not git commit during a rebase. --continue does it.
What Not To Do
Do not run git rebase -i on a branch someone else has pulled. Everything in this module rewrites commits, which is the definition of what the Golden Rule forbids. Clean up before the branch goes out, not after.
Key Takeaways
git rebase -i <base>opens an editable plan of the commits to be replayed- The todo list is oldest first, the opposite of
git log git rebase -i mainis safer than counting withHEAD~n- Six commands:
pick,reword,edit,squash,fixup,drop— plus reordering - Saving without changes is a no-op, so opening the list to look is free
--continue,--abortand--skipbehave exactly as in a plain rebase- Interactive rebase rewrites history, so it is for branches nobody else has pulled