pickuma.
Dev Knowledge

Merge vs Rebase: What Git Is Really Doing

A clear explainer of git merge versus git rebase — how each one rewrites or preserves history, what tradeoffs you accept, and the one rule you must never break.

5 min read

Both git merge and git rebase exist to do the same job — integrate changes from one branch into another. They produce different histories because they go about it in fundamentally different ways, and understanding that difference is what stops you from corrupting a shared branch.

What merge actually does

A merge takes the work from two branches and joins them with a single new commit — the merge commit. That commit is unusual because it has two parents: the tip of the branch you were on, and the tip of the branch you pulled in. Every commit on both branches stays exactly where it was, untouched. Git just adds one node on top that says “these two lines of history came together here.”

Suppose you branched feature off main, and while you worked, someone else pushed commits to main. When you run git merge main from your feature branch, Git finds the common ancestor of the two branches, computes the changes on each side since then, combines them, and records the result as the merge commit.

main: A---B---C---D
\ \
feature: E---F---M ← M is the merge commit (parents: F and D)

The payoff is that your history is true. You can see that E and F happened on a side branch, in parallel with C and D, and were joined at M. Nothing is invented or rewritten. The cost is that the graph gets bushy — a busy repo with many merges produces a tangled web that can be hard to read in a log.

What rebase actually does

A rebase does not join histories. It moves them. When you run git rebase main from your feature branch, Git takes each of your commits, sets them aside, fast-forwards your branch to the tip of main, and then replays your commits one at a time on top.

main: A---B---C---D
\
feature: E'---F' ← replayed copies of E and F

Notice E' and F', not E and F. They are new commits. A commit’s hash is derived from its content plus its parent, and rebasing gives each commit a new parent — so every replayed commit gets a brand-new hash. The original E and F still exist for a while in Git’s internals, but your branch no longer points at them. The result is a straight line, as if you had branched from the current tip of main all along. No merge commit, no fork in the graph — just a clean, linear story.

That linearity is the whole appeal. git log reads top to bottom like a changelog, git bisect walks a simple sequence, and reviewers see your work as a tidy series of steps rather than a snapshot of parallel chaos.

The tradeoff, and the one rule

The core difference is this: merge is non-destructive and preserves context; rebase is destructive and rewrites it. Merge keeps the real, sometimes-messy shape of how work happened. Rebase manufactures a cleaner shape by discarding the old commits and creating new ones in their place.

Neither is “correct.” A common workflow is to rebase your own local feature branch to tidy it up before sharing, then merge it into main so the integration point is explicit. The line you must not cross is rewriting history that other people already have.

A useful mental shortcut: rebase is for cleaning up your own work before anyone sees it; merge is for combining work that is already public. If you remember only one thing, remember that rebasing public history breaks collaborators.

FAQ

FAQ

Does merge or rebase change my actual code?+
Neither changes the final file contents you end up with — both integrate the same set of changes. What differs is the recorded history: merge adds a merge commit and keeps both branch lines, while rebase rewrites your commits into a single linear sequence with new hashes.
Why do my commit hashes change after a rebase?+
A commit's hash is computed from its content and its parent commit. Rebase replays your commits onto a new base, which gives each one a different parent, so Git produces an entirely new hash for every replayed commit. The originals are orphaned, not edited in place.
I accidentally rebased a shared branch — can I recover?+
Usually yes. 'git reflog' records where your branch pointed before the rebase, so you can reset back to the old commit and restore the original history. Coordinate with teammates before force-pushing again, since their clones may still hold the pre-rebase or post-rebase state.

Related reading

See all Dev Knowledge articles →

Get the best tools, weekly

One email every Friday. No spam, unsubscribe anytime.