Merge vs rebase, watched one commit at a time
Merge records what happened. Rebase rewrites it into what you wish had happened.
Both end with your work on top of main. The difference is what the graph looks
like afterwards, and whether the commits that get there are the same commits
you started with.
The same diverged branch, resolved two ways
1 / 3git merge
main is at E. Your branch is at D. They share B as an ancestor.
git rebase
Identical starting point. main is at E, your branch is at D.
You branched off main at B and made two commits. While you worked, main moved on to E. Neither history is wrong: they just disagree about what came after B.
The bit everyone misses
Watch the second step again. Under rebase, C and D do not move. They are
replaced. Git replays each change onto the new base and produces a new
commit for each one, with a new parent, a new timestamp and therefore a new SHA.
That is why rebasing a branch someone else has already pulled is such a
problem. Their clone still has the old C and D. Yours has C' and D'.
Git has no way to know these are "the same" work, so the next time they pull,
they get both, and a conflict-riddled mess trying to reconcile them.
| git merge | git rebase | |
|---|---|---|
| Existing commits | Untouched. Same SHAs forever. | Replaced. Every replayed commit gets a new SHA. |
| New commits created | One merge commit, with two parents. | One per commit replayed. |
| Resulting history | A fork you can still see years later. | A straight line, as if no branch happened. |
| Conflicts | Resolved once, in the merge commit. | Resolved per commit: you can hit the same one repeatedly. |
| Safe on a shared branch? | Yes. It only ever adds. | No. It rewrites history others may already have. |
| Reverting it later | git revert -m 1: one commit to undo. | No single commit to undo; you unpick each one. |
What teams actually do
Most healthy repos use both, and split them by who has seen the commits:
- Rebase your own branch before you open the PR. Nobody else has those commits yet, so rewriting them is free, and it gives reviewers a clean, linear diff instead of six "merge main into feature" commits.
- Merge the PR into
main. The merge commit is the record that this body of work landed as one unit, andmainis shared, so it must never be rewritten.
The one-line rule that follows from all of this: rebase before you push, merge after.
Remember this
- 1Rebase does not move commits. It replaces them. New parent, new SHA, new object.
- 2Never rebase anything that has already been pushed to a branch other people pull. Their clone still has the originals.
- 3A merge commit has two parents. That is the single fastest way to spot one in a log.