Skip to main content

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

ScenarioSafe 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 + --autosquash for the cleanest workflow
  • Keep commit scopes small — easier to reorder and squash
  • Always rebase your feature branch onto main before merging
  • Never rebase shared history

What's Next

  1. Cherry-Pick & Bisect — Select specific commits and find bug introductions
  2. Hooks & Automation — Automate tasks with Git hooks