Difficulty: Intermediate
Explain git rebase in depth. What is interactive rebase and how do you use it to clean up commit history?
git rebase takes a series of commits and replays them on top of another base commit. Unlike merge, which creates a merge commit preserving the branching structure, rebase produces a clean, linear history as if you had made your changes starting from the latest point on the target branch.
Interactive rebase (git rebase -i) is one of Git's most powerful features. It lets you rewrite local commit history by reordering, editing, squashing, splitting, or dropping commits. Common operations: - pick: keep the commit as-is - reword: change the commit message - squash: combine with the previous commit, edit the message - fixup: combine with previous commit, discard the message - edit: pause to amend the commit - drop: remove the commit entirely
The golden rule: never rebase commits that have been pushed to a shared branch. Rebase rewrites commit hashes, which creates divergent histories for anyone who has already pulled those commits. Use rebase only on your local, unpushed feature branches.
# Before rebase:
# main: A - B - C - D
# \
# feature: E - F - G
# Rebase feature onto latest main
git checkout feature/auth
git rebase main
# After rebase:
# main: A - B - C - D
# \
# feature: E' - F' - G'
# (E', F', G' are NEW commits with new hashes)
# Then fast-forward merge on main
git checkout main
git merge feature/auth
# Result: A - B - C - D - E' - F' - G' (linear!)
# If conflicts during rebase:
# 1. Fix the conflict in the file
# 2. git add <resolved-files>
# 3. git rebase --continue
# Repeat for each conflicting commit
# Abort rebase (return to pre-rebase state)
git rebase --abort
# Skip a conflicting commit
git rebase --skip
Rebase replays your commits one by one onto the new base. If any commit conflicts, you resolve it and continue. The result is a clean linear history.
# Rewrite last 4 commits
git rebase -i HEAD~4
# Editor opens with:
# pick a1b2c3d feat: add login form
# pick e4f5g6h fix: typo in login
# pick i7j8k9l fix: another typo
# pick m0n1o2p feat: add validation
# Squash typo fixes into the main commit:
# pick a1b2c3d feat: add login form
# fixup e4f5g6h fix: typo in login
# fixup i7j8k9l fix: another typo
# pick m0n1o2p feat: add validation
# Result: 2 clean commits instead of 4
# Reorder commits (just move lines):
# pick m0n1o2p feat: add validation
# pick a1b2c3d feat: add login form
# Edit a commit message:
# reword a1b2c3d feat: add login form
# (Editor opens to change the message)
# Edit a commit's content:
# edit a1b2c3d feat: add login form
# (Pauses at that commit, you make changes)
# git add .
# git commit --amend
# git rebase --continue
# Drop a commit:
# drop e4f5g6h fix: typo in login
# (or just delete the line)
Interactive rebase is your commit cleanup tool. Squash noise commits, reword messages, reorder for logical grouping. Always do this BEFORE pushing.
# Rebase onto: move branch to a different base
# Before:
# main: A - B - C
# \
# feature: D - E
# \
# sub-feature: F - G
# Move sub-feature directly onto main (skip feature)
git rebase --onto main feature sub-feature
# After:
# main: A - B - C
# | \
# feature: D - E \
# sub-feature: F' - G'
# Autosquash: auto-arrange fixup commits
# When committing fixes:
git commit --fixup=a1b2c3d
# Creates: "fixup! feat: add login form"
# Later, interactive rebase auto-sorts them:
git rebase -i --autosquash HEAD~5
# The fixup commit is automatically placed after its target
# Enable autosquash by default
git config --global rebase.autosquash true
# Rebase preserving merge commits
git rebase --rebase-merges main
# (replaces deprecated --preserve-merges)
--onto lets you transplant a branch to a completely different base. --autosquash + --fixup workflow is how professionals keep clean history while developing.
git rebase, Interactive Rebase, Squash, Fixup, Reword, Rebase Onto