Merging vs Rebasing
Back to the novel analogy: you photocopied the manuscript, rewrote chapter 3 on the copy, and it worked out great. Now you need to get that rewrite back into the master copy. You have two honest ways to do it: staple the copy's chapter 3 into the master and note "chapter 3 was replaced on this date" (a merge), or carefully retype the rewrite in-place as if you'd written it there from the start, so the master reads as one clean draft (a rebase). Git gives you both options, and they solve the same problem with a different trade-off.
💡 The Bottom Line
git merge combines two branches by creating a new commit that ties their
histories together, preserving exactly what happened. git rebase replays your
branch's commits on top of another branch, producing a straight, linear history as if you'd
branched later than you actually did. Merge is safer and preserves true history; rebase is
cleaner-looking but rewrites commits, so it comes with real caution rules.
Merging: honest, if a little messy
git switch main
git merge feature/login-form
If main hasn't moved since you branched, this is a "fast-forward" merge — Git
just slides the main pointer forward, no new commit needed. But if both branches
have new commits, Git creates a merge commit: a special commit with two
parents, one from each branch, stitching the two histories together. Nothing is rewritten;
every commit that ever existed on either branch is still there, in the order it really
happened.
Rebasing: rewriting for a straight line
git switch feature/login-form
git rebase main
This takes every commit unique to feature/login-form and replays it, one by
one, on top of the current tip of main — as if you'd started your branch from
there in the first place. The result is a clean, linear history with no merge commits. The
catch: those replayed commits are technically brand-new commits (new hashes), even though the
changes look the same. The originals are effectively discarded.
⚠️ Watch Out
Never rebase commits that other people have already pulled and built on. Because rebase rewrites commit history, anyone who already has the old commits will have their history diverge painfully from yours the next time they pull. The standard rule of thumb: rebase freely on your own local, not-yet-shared branches; merge (never rebase) once a branch is shared with others.
When to use which
- Use merge when combining a finished feature branch into
main, or whenever the branch is shared with others — it's non-destructive and keeps the true story of what happened. - Use rebase to tidy up your own local branch before sharing it — for
example, pulling in the latest
mainso your feature branch applies cleanly on top, without a tangle of unrelated merge commits in your personal history.
🙋 There Are No Dumb Questions
Q: If rebase makes history "look" cleaner, why doesn't everyone just always rebase?
A: Because "cleaner-looking" comes at the cost of rewriting commits, which is dangerous the
moment other people depend on those commits. A linear history is nice to read, but not worth
the risk of scrambling a teammate's branch. Many teams simply standardize on merge for
anything shared, and save rebase for tidying up strictly personal, unpublished work.
Merge conflicts: when Git needs your judgment
Both merging and rebasing can hit a conflict — when the same lines of a file were changed differently on both sides, and Git can't guess which version is right. Git pauses and marks the file:
<<<<<<< HEAD
const greeting = "Hello there!";
=======
const greeting = "Hi, welcome!";
>>>>>>> feature/login-form
Resolving it means editing the file to keep the version you want (or a blend of both),
removing the <<<<<<< / ======= /
>>>>>>> markers entirely, then telling Git it's resolved:
git add greeting.js
git commit # finishes a merge conflict
# or, mid-rebase:
git rebase --continue
If a conflict looks too tangled to sort out, you can always back out cleanly:
git merge --abort
git rebase --abort
🔧 Try It Yourself
Deliberately create and resolve a conflict:
git switch -c branch-a
echo "Version A" > note.txt
git add note.txt && git commit -m "Write version A"
git switch main
echo "Version B" > note.txt
git add note.txt && git commit -m "Write version B"
git merge branch-a
Git will report a conflict in note.txt. Open the file, pick a final version,
remove the conflict markers, then run git add note.txt and
git commit to complete the merge.
✅ Quick Check
Why is it risky to rebase a branch that other people have already pulled?
Next up: none of this matters much until your work leaves your laptop. Time to look at remotes and how collaboration actually works with GitHub.