Great work!

XP to next level

BugEater
EN

Opening the Todo List: git rebase -i

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 main to git rebase -i HEAD~n. Counting commits by hand is how people accidentally include a commit from main in the range — and rewriting a commit that is on main breaks 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 main is safer than counting with HEAD~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, --abort and --skip behave exactly as in a plain rebase
  • Interactive rebase rewrites history, so it is for branches nobody else has pulled

Quiz

In what order does the interactive rebase todo list show commits?

Why is git rebase -i main usually better than git rebase -i HEAD~6?

You open the todo list, change nothing, and save. What happens?

During an interactive rebase Git stops for a reword. You edit the message. What do you run?