Saltar al contenido principal

git rebase — Linear and Clean History

Module 02 60 min

Section Objectives

  • Understand what git rebase does
  • 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?

CriterionMergeRebase
HistoryPreserves exact historyCreates linear history
Merge commitsYes (creates one)No
TraceabilityComplete (who merged what when)Less obvious
ReadabilityCan become messy with many branchesClean and linear
Safety for shared branchesAlways safeNEVER on shared branches
Code reviewsEasier to see contextEasier to read line by line

The Golden Rule of Rebase

Golden Rule

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

# 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

CommandDescription
git rebase mainRebase current branch onto main
git rebase -i HEAD~NInteractive rebase on last N commits
git rebase --continueContinue after resolving conflict
git rebase --abortCancel the rebase
git rebase --skipSkip current conflicted commit
git pull --rebasePull with rebase

Next Steps