Merge vs Rebase

Course 2 · Ch 2
Merge vs Rebase
What's actually happening under the hood with each, and when to reach for one over the other

Course 1 introduced git merge as the way to bring a branch's work back together. There's a second tool for the same general goal — git rebase — and the two produce genuinely different history, not just different commands for the same outcome. Understanding that difference is what lets you choose deliberately instead of by habit.

The Setup — A Diverged Branch

Both examples in this chapter start from the same situation: a feature branch with two commits, while main has gained one commit of its own in the meantime.

main c1 c2 feature f1 f2
main gained c2 while feature was being worked on — both branches diverged from c1

Option A: git merge

Merging creates a brand-new commit with two parents — one pointing back into main's history, one pointing back into feature's history. Nothing about either branch's existing commits changes; the merge commit simply ties them together.

$ git switch main
$ git merge feature
Merge made by the 'ort' strategy.
merge
A new merge commit ties both histories together — c1, c2, f1, and f2 are all still visible, exactly as they happened

Option B: git rebase

Rebasing takes a completely different approach: it replays your branch's commits, one at a time, as if they'd been written starting from the tip of main all along — rather than tying two histories together, it rewrites feature to look like it always branched off the newest point.

$ git switch feature
$ git rebase main
Successfully rebased and updated refs/heads/feature.
c1 c2 f1' f2'
f1 and f2 are recreated as f1' and f2' — same changes, brand new commit hashes, now sitting cleanly after c2 in a single straight line
f1' and f2' are NOT the same commits as f1 and f2
This is the single most important thing to understand about rebasing: even though the file changes are identical, rebasing creates entirely new commits with new hashes. The originals still technically exist in git's internal storage for a while (recoverable via git reflog — Course 3, Chapter 3), but as far as any branch or remote is concerned, feature now points at a different, rewritten history. This is exactly why rebasing a branch others have already pulled is dangerous — covered in the warning below.

Comparing the Results

🔀
merge
History: Branching, non-linear — shows exactly when and how branches diverged and came back together.

Safety: Always safe, even on shared/pushed branches — never rewrites existing commits.

Downside: Can produce a tangled-looking history with many merge commits on an active project.
📏
rebase
History: Linear, clean — reads top to bottom with no branching/merging visual noise.

Safety: Safe only on branches nobody else has pulled yet — rewrites commit hashes.

Downside: Loses the literal record of when divergence happened; rewritten hashes can conflict with collaborators' copies.

When to Use Each

SituationUse
Bringing a finished feature branch into main via a PRmerge (often via the PR's own "Merge" button — Course 1, Ch7)
Catching your local feature branch up with main before continuing workrebase — keeps your branch's history clean as you go
The branch has already been pushed and others have pulled itmerge only — never rebase shared history
Cleaning up your own messy local commits before opening a PRinteractive rebase (full coverage in Course 3, Ch2)
Unsure, or working solo on a small projectmerge — fewer ways to get into trouble
The golden rule, again: never rebase a branch others have already pulled
This is the same underlying principle from Course 1, Chapter 8's revert-vs-reset rule, applied to rebasing: rewriting history that someone else has already built on top of creates a divergence between your rewritten version and their original — the foundation of the force-push problems covered later in this course (Chapter 9) and the disaster-recovery chapter in Course 3.

A common middle ground: rebase locally, merge for the PR

Many developers rebase their own feature branch against main repeatedly while working on it solo (keeping their personal history clean, before anyone else has seen it), then let the actual PR merge into main happen as a normal merge — getting a clean personal workflow without ever rebasing anything that's been shared.

Chapter 2 Quick Reference

  • git merge — creates a new commit with two parents; preserves exact history; always safe
  • git rebase — replays your commits on top of the target branch; creates new commit hashes; linear, clean history
  • Critical distinction: rebase rewrites commits — the originals are effectively gone from that branch's perspective
  • Golden rule: never rebase a branch that's already been pushed and pulled by someone else
  • Common pattern: rebase your own unshared branch to stay current with main; merge for the final PR into main
  • When unsure: default to merge — it's never the wrong choice, just sometimes the less tidy one
  • Next chapter: resolving conflicts properly — tools, strategies, and aborting safely when it goes wrong