datarekha

Rebase vs merge

Should you merge main into your feature branch or rebase onto it? Learn what each does to history and when to pick which.

9 min read Intermediate Git Lesson 10 of 15

What you'll learn

  • What rebase does: it replays your commits on top of another branch, rewriting their SHAs into a linear chain
  • When to choose merge (preserve true history) vs rebase (clean linear log)
  • Interactive rebase with git rebase -i: squash, reword, and drop commits before sharing

Before you start

The setup: two branches that have diverged

Suppose main has moved forward since you branched off. Your feature branch has two commits (F1, F2) and main has gained one (M1):

main:    A --- B --- M1
                \
feature:         F1 --- F2

You need to incorporate M1 into your feature branch. You have two options.


Option 1: Merge

Running git merge main from your feature branch creates a new merge commit (Mc) that has two parents — the tip of your branch and the tip of main.

# from your feature branch
git merge main
main:    A --- B --- M1
                \       \
feature:         F1 --- F2 --- Mc

The merge commit records exactly when and how the two lines of work joined. That is the entire point: the history is a faithful record of what actually happened.

Merge trade-offs

ProsCons
Preserves the true branching historyMerge commits add noise to git log on busy projects
Safe — never rewrites existing SHAsHistory can look tangled with many parallel branches
Ideal for long-lived, shared branches

Option 2: Rebase

Rebase (short for “re-apply onto a new base”) takes each of your branch’s commits and replays them — one by one — on top of the tip of the target branch. Each replayed commit gets a brand-new SHA because its parent has changed.

# from your feature branch
git rebase main

Git detaches your commits and re-applies them:

Before:
main:    A --- B --- M1
                \
feature:         F1 --- F2

After rebase:
main:    A --- B --- M1
                         \
feature:                  F1' --- F2'

F1' and F2' contain the same diffs as F1 and F2, but they have new SHAs and M1 is their ancestor. There is no merge commit — the result is a linear history.

Rebase trade-offs

ProsCons
Linear, easy-to-read git logRewrites SHAs — dangerous if others have your commits
No merge commit noiseConflicts must be resolved commit-by-commit
Makes git bisect and git log --oneline cleanerObscures the true parallelism of the work

Side-by-side diagram

git merge mainABM1mainF1F2Mcmergegit rebase mainABM1mainF1ʼnew SHAF2ʼnew SHALinear history — no merge commit
Left: merge preserves both lines of history with a merge commit (Mc). Right: rebase replays commits on top of main, producing a single linear chain with new SHAs (F1ʼ, F2ʼ).

Resolving conflicts during a rebase

Because rebase replays commits one at a time, a conflict can appear at any replay step. Git pauses and tells you which commit it is applying:

git rebase main
# CONFLICT (content): Merge conflict in src/auth.ts
# error: could not apply f1a3c2e... Add login validation

Fix the conflict in your editor, stage the resolved file, then continue:

# after editing the conflicted file
git add src/auth.ts
git rebase --continue

Git moves on to the next commit and repeats until done. If you want to bail out entirely:

git rebase --abort   # restores the branch to its pre-rebase state

The Golden Rule


Interactive rebase: tidying up before you share

git rebase -i (interactive rebase) lets you rewrite the history of your own local commits before pushing. You can squash noisy “WIP” commits into one clean commit, reword a message, or drop an accidental commit entirely.

# rewrite the last 3 commits interactively
git rebase -i HEAD~3

Git opens an editor with a list of commits and action keywords:

pick a1b2c3f Add login validation
pick 9d4e5f6 WIP: fix typo
pick 3c7a8b9 Fix edge case in token expiry

# Commands:
# p, pick   = use commit as-is
# r, reword = use commit but edit the message
# s, squash = fold into the previous commit
# d, drop   = remove the commit entirely

Change pick to squash on the second line and save:

pick a1b2c3f Add login validation
squash 9d4e5f6 WIP: fix typo
pick 3c7a8b9 Fix edge case in token expiry

Git combines the first two commits and prompts you for a combined message. The result is a cleaner two-commit history ready to push as a PR.

Interactive rebase is powerful precisely because it operates only on local, un-pushed commits — which is exactly where the Golden Rule permits rewriting.


When to use which

SituationReach for
Syncing a local feature branch with main before opening a PRgit rebase main
Merging a finished PR into main on GitHubgit merge (or a squash merge via the UI)
Combining noisy WIP commits before pushinggit rebase -i
Long-lived shared branches that multiple people push togit merge
You want a permanent record that two features were developed in parallelgit merge

Quick check

0/3
Q1After running `git rebase main` on your feature branch, what is true about your branch's commits?
Q2A colleague pulled your feature branch yesterday. You then ran `git rebase main` and force-pushed the branch. What problem does this cause?
Q3Your team uses short-lived feature branches and squashes them when merging to main. A new teammate suggests always using `git merge` with `--no-ff` on the feature branch itself (to keep a record of every WIP commit in main's history). What is the strongest argument against this for your workflow?

Sign in to track your progress

Completed lessons, your XP, level, and streak save to your account — it's free and takes a few seconds.

Explore further

Glossary terms
Cheat sheets

Related lessons

Skip to content