git rebase — Linear and Clean History
Section Objectives
- Understand what
git rebasedoes - Know the difference between merge and rebase
- Use interactive rebase to clean up history
- Know the golden rule: never rebase public history
What is Rebase?
git rebase moves or replays commits onto a different base. Instead of creating a merge commit, it rewrites the commit history to appear as if you branched off from a newer point.
Merge vs Rebase — Visual Comparison
Situation: feature branch diverged from main
After git merge main (merge approach):
After git rebase main (rebase approach):
With rebase, commits C4 and C5 are replayed on top of C3 — creating new commits (C4', C5') with the same changes but different parents.
Basic Rebase
# Scenario: you're on feature/login, want to integrate latest main
git switch feature/login
git rebase main
# Step by step: Git does this automatically:
# 1. Find common ancestor of feature/login and main
# 2. Save commits from feature/login (as patches)
# 3. Reset feature/login to point to main's HEAD
# 4. Re-apply saved commits one by one
Handle Conflicts During Rebase
# If a conflict occurs during rebase:
# 1. Fix the conflict in the file
git status # Shows conflicted files
# 2. Mark as resolved
git add conflicted-file.py
# 3. Continue the rebase
git rebase --continue
# OR: Abort the entire rebase
git rebase --abort
# OR: Skip this specific commit
git rebase --skip
Interactive Rebase — The Most Powerful Tool
Interactive rebase lets you edit your history before sharing it:
# Rebase the last 4 commits interactively
git rebase -i HEAD~4
# Rebase commits since branching from main
git rebase -i main
This opens an editor with a list of commits and actions:
pick a3f4b2c feat: add login form
pick b7c9d1e fix: typo in login
pick c2e8f3a WIP commit
pick d5a1b4c feat: add JWT validation
# Commands:
# p, pick = use commit as-is
# r, reword = edit commit message
# e, edit = pause to amend commit
# s, squash = merge into previous commit
# f, fixup = merge into previous (discard message)
# d, drop = remove commit
Interactive Rebase Use Cases
Squash multiple commits into one:
pick a3f4b2c feat: add login form
s b7c9d1e fix: typo in login
s c2e8f3a WIP commit
pick d5a1b4c feat: add JWT validation
→ Result: 2 clean commits instead of 4 messy ones
Reorder commits:
pick d5a1b4c feat: add JWT validation ← moved up
pick a3f4b2c feat: add login form
pick b7c9d1e fix: typo in login
Drop (delete) a commit:
pick a3f4b2c feat: add login form
d b7c9d1e debug: temp console.log ← removed
pick c2e8f3a feat: add tests
Reword a commit message:
r a3f4b2c feat: add login form ← will prompt for new message
pick b7c9d1e fix: correct validation
Merge vs Rebase — Which to Use?
| Criterion | Merge | Rebase |
|---|---|---|
| History | Preserves exact history | Creates linear history |
| Merge commits | Yes (creates one) | No |
| Traceability | Complete (who merged what when) | Less obvious |
| Readability | Can become messy with many branches | Clean and linear |
| Safety for shared branches | Always safe | NEVER on shared branches |
| Code reviews | Easier to see context | Easier to read line by line |
The Golden Rule of Rebase
Never rebase commits that have already been pushed to a shared branch.
Rebase rewrites history (creates new commits with new hashes). If others have based work on your old commits, this creates confusion and complex conflicts.
Safe: Rebase on a local branch before pushing
Dangerous: Rebase after pushing to main, develop, or any shared branch
Recommended Strategy
# Personal workflow (local branch, not yet pushed)
✅ git rebase -i HEAD~5 # Clean up history before pushing
# Staying up to date with main
✅ git rebase main # On your local feature branch
# After pushing to a shared branch
❌ git rebase # NEVER rebase published commits
✅ git merge # Always safe
git pull --rebase
# Pull with rebase instead of merge (cleaner local history)
git pull --rebase
# Configure as default for all pulls
git config --global pull.rebase true
Practical Example: Clean History Before PR
# You worked on a feature with 6 commits
git log --oneline
# abc123 WIP
# def456 fix typo
# ghi789 fix another typo
# jkl012 oops forgot to add file
# mno345 feat: login form
# pqr678 feat: initial login page
# Clean up before creating a PR
git rebase -i HEAD~6
# In the editor:
# pick pqr678 feat: initial login page
# s mno345 feat: login form
# s jkl012 oops forgot to add file
# s ghi789 fix another typo
# s def456 fix typo
# s abc123 WIP
# After squash, write a clean commit message:
# feat(auth): complete login page with form and validation
# Push the clean single commit
git push origin feature/login
Summary
| Command | Description |
|---|---|
git rebase main | Rebase current branch onto main |
git rebase -i HEAD~N | Interactive rebase on last N commits |
git rebase --continue | Continue after resolving conflict |
git rebase --abort | Cancel the rebase |
git rebase --skip | Skip current conflicted commit |
git pull --rebase | Pull with rebase |
Next Steps
- Hands-on Lab TP3 — Branches, merge, rebase in practice
- Module 03 - GitHub & Remotes