Interactive Rebase
Quick Summary
Interactive rebase (git rebase -i) lets you rewrite history commit-by-commit. You can reorder commits, squash messy "WIP" commits into one clean commit, edit commit messages, split commits, or drop commits entirely. It's the tool for polishing your branch before merging.
Starting Interactive Rebase
# Rebase last N commits
git rebase -i HEAD~4
# Rebase onto a specific branch
git rebase -i main
Git opens your editor with a list of commits:
pick a1b2c3d feat: add login form
pick b2c3d4e fix: typo in login
pick c3d4e5f WIP: debugging
pick d4e5f6a feat: add validation
# Commands:
# p, pick = use commit as-is
# r, reword = edit the commit message
# e, edit = pause to amend the commit
# s, squash = merge into previous commit (keep message)
# f, fixup = merge into previous commit (discard message)
# d, drop = delete the commit
# x, exec = run a shell command
Common Operations
Squash Multiple Commits
pick a1b2c3d feat: add login form
fixup b2c3d4e fix: typo in login # ← merge into above, discard message
fixup c3d4e5f WIP: debugging # ← merge into above, discard message
pick d4e5f6a feat: add validation
Result: 4 commits → 2 clean commits
Reorder Commits
pick d4e5f6a feat: add validation # ← moved up
pick a1b2c3d feat: add login form
Edit a Commit Message
reword a1b2c3d feat: add login form # ← Git will prompt for new message
pick d4e5f6a feat: add validation
Split a Commit
edit a1b2c3d feat: add login + validation # ← pause here
When Git pauses:
# Undo the commit but keep changes staged
git reset HEAD~1
# Stage and commit separately
git add src/login.js
git commit -m "feat: add login form"
git add src/validation.js
git commit -m "feat: add validation"
# Continue the rebase
git rebase --continue
Drop a Commit
pick a1b2c3d feat: add login form
drop c3d4e5f WIP: debugging # ← deleted entirely
pick d4e5f6a feat: add validation
Autosquash (Fixup Workflow)
The fastest way to fix previous commits:
# Make the fix and commit with --fixup
git commit --fixup=a1b2c3d
# Later, autosquash (auto-reorder and squash fixups)
git rebase -i --autosquash main
Git automatically marks fixup commits and places them next to their targets.
Enable autosquash by default:
git config --global rebase.autosquash true
Safety Rules
Golden Rule
Never rebase commits that have been pushed to a shared branch. Rebasing changes commit hashes, which breaks other developers' history.
Safe: Rebasing your local, unpushed feature branch
Dangerous: Rebasing main or any shared branch
| Scenario | Safe to Rebase? |
|---|---|
| Local commits, never pushed | ✅ Always safe |
| Your branch, only you use it | ⚠️ Use --force-with-lease to push |
| Shared branch with other devs | ❌ Never |
| Already-merged commits | ❌ Never |
Recovery
# Abort a rebase in progress
git rebase --abort
# Find commits before the rebase (in reflog)
git reflog
# Restore: git reset --hard HEAD@{N}
Best Practices
- Squash "fix typo" and "WIP" commits before creating a PR
- Use
--fixup+--autosquashfor the cleanest workflow - Keep commit scopes small — easier to reorder and squash
- Always rebase your feature branch onto
mainbefore merging - Never rebase shared history
What's Next
- Cherry-Pick & Bisect — Select specific commits and find bug introductions
- Hooks & Automation — Automate tasks with Git hooks