Skip to content

Drill: Interactive Rebase to Clean Up Commits

Goal

Use interactive rebase to squash, reorder, and edit commits before pushing to create a clean commit history.

Setup

  • A git repository with several small or messy commits on a feature branch
  • Commits that have NOT been pushed to a shared remote

Commands

Set up a practice scenario:

mkdir /tmp/rebase-drill && cd /tmp/rebase-drill && git init
echo "base" > file.txt && git add file.txt && git commit -m "initial"
echo "v1" >> file.txt && git add file.txt && git commit -m "WIP: start feature"
echo "v2" >> file.txt && git add file.txt && git commit -m "fix typo"
echo "v3" >> file.txt && git add file.txt && git commit -m "WIP: more progress"
echo "v4" >> file.txt && git add file.txt && git commit -m "actually fix the thing"
echo "v5" >> file.txt && git add file.txt && git commit -m "cleanup"

View the commits to be rebased:

git log --oneline

Start interactive rebase (last 5 commits):

GIT_SEQUENCE_EDITOR="sed -i '2s/pick/squash/;3s/pick/squash/;4s/pick/squash/;5s/pick/squash/'" git rebase -i HEAD~5

The rebase todo list uses these commands: - pick - keep the commit as-is - squash (s) - combine with previous commit, edit message - fixup (f) - combine with previous commit, discard message - reword (r) - keep commit but edit message - drop (d) - remove the commit entirely

To reorder commits, change the line order in the editor.

After conflicts during rebase:

# Resolve conflicts in files
git add <resolved-files>
git rebase --continue

Abort a rebase in progress:

git rebase --abort

What to Look For

  • After squashing, multiple commits become one with a combined message
  • fixup is like squash but automatically discards the commit message
  • Reordering commits may cause conflicts if later commits depend on earlier ones
  • The reflog preserves the pre-rebase state for recovery

Common Mistakes

  • Rebasing commits that have already been pushed to a shared branch
  • Squashing all commits into one when some logical separation is valuable
  • Not checking git log after rebase to verify the result looks correct
  • Forgetting that rebase rewrites commit hashes (all downstream refs change)

Cleanup

rm -rf /tmp/rebase-drill