Git Rebase vs Merge: The Only Explanation That Sticks

Merge joins two histories with a new commit. Rebase lifts your commits off the branch and replays them on top of the latest code. Get that one picture and every rebase-vs-merge argument suddenly makes sense.

Tech Talk News Editorial8 min read
ShareXLinkedInRedditEmail
Git Rebase vs Merge: The Only Explanation That Sticks

Key takeaways

  • Git merge combines two branches by doing a three-way merge and writing one new merge commit that has two parents, so the branching history is preserved exactly as it happened.
  • Git rebase takes the commits unique to your branch, sets them aside, moves your branch to the tip of the target branch, and replays each commit on top, producing a straight line with no merge commit.
  • The golden rule of rebasing, straight from the Pro Git book, is to never rebase commits that exist outside your repository and that other people may have based work on.
  • Interactive rebase (git rebase -i) is the real reason to learn rebase: six core commands (pick, reword, edit, squash, fixup, drop) let you rewrite your local history into a clean series before anyone reviews it.
  • The sane team default is rebase your own local branch to clean it up before pushing, then merge it into main, which is the "best of both worlds" the Pro Git book recommends.

Almost every explanation of git rebase vs merge fails you in the same spot. It tells you rebase “rewrites history” and merge “preserves history,” nods gravely, and moves on. That is true and completely useless, because you still don't have a picture in your head of what actually happens to your commits. So you keep guessing, and you keep being a little afraid of rebase. Let me give you the one mental model that makes it click and never leave.

Here it is in one breath. Merge takes two branches and ties them together with a new commit. Both histories stay exactly as they happened, and a fresh merge commit sits on top pointing back at both.[2] Rebase lifts the commits off your branch, moves your branch to the tip of the other branch, and replays your commits one at a time on top of it.[2]No merge commit. Just a clean straight line, as if you had started your work from the latest code all along. That's the whole thing. Everything else is a consequence of those two pictures.

Plain English

Merge is a handshake between two histories: nothing gets rewritten, and a new commit records that they met. Rebase is a do-over: your commits get re-recorded on top of newer code, so the branch looks like it never diverged in the first place.

The Picture: Replay-On-Top vs New-Commit

Say you branched off main to build a feature. While you worked, two commits landed on main from your teammates. Now your branch and main have diverged. You need the new stuff from main in your branch. You have two moves.

If you merge, Git does a three-way merge. It looks at the tip of your branch, the tip of main, and the last commit they had in common, works out the combined result, and writes a brand-new merge commit that has two parents, one on each branch.[2]Your commits are untouched. Their commits are untouched. The history now has a little diamond shape in it that says “these two lines of work happened at the same time and joined here.”

If you rebase, Git finds the commits that are unique to your branch, tucks them away as patches, fast-forwards your branch to the current tip of main, and then re-applies your patches one after another on top.[3] The result is a single straight line: all of main, then your commits, in order, with no diamond and no merge commit. As the Pro Git book puts it, rebasing “replays changes from one line of work onto another in the order they were introduced, whereas merging takes the endpoints and merges them together.”[2]

Merge records what happened. Rebase edits the story so it reads better. Both are legitimate; they just answer different questions.

Sit with that word replays, because it carries the one detail that trips everyone up. When rebase re-applies your commits, it creates new commits. Same changes, same messages, but brand-new commit IDs, because a commit's ID is computed from its parent, and you just gave every commit a different parent. The old commits don't vanish, they sit in your reflog for a couple of weeks, but your branch no longer points at them. This is what “rewrites history” actually means. Not deletion. Re-recording.

1
two parents
Merge commit added by a merge
0
straight line
Merge commits added by a rebase
New IDs
same changes
What rebase gives every replayed commit

The Golden Rule, Stated Bluntly

Now that you know rebase re-records commits with new IDs, the one rule that governs all of this writes itself. From the Pro Git book, and I want you to memorize this sentence:

Do not rebase commits that exist outside your repository and that people may have based work on.
Pro Git, Git Branching, Rebasing

That's it. That's the golden rule of rebasing, and it is not a style suggestion, it is a load-bearing safety rule.[1]Here is why it matters, in concrete terms. Suppose you push your feature branch, a teammate pulls it and starts building on your commits, and then you rebase that branch and force-push it. Your commits now have new IDs. Your teammate's copy still points at the old IDs. Git looks at the two and sees two completely different sets of commits that happen to contain the same changes, and it cannot reconcile them cleanly. Your teammate has to untangle it by hand. Pro Git's exact warning is that if you break this rule, “people will hate you, and you'll be scorned by friends and family.”[2]The official git-rebase docs put it more dryly: rebasing a branch others have based work on “is a bad idea: anyone downstream of it is forced to manually fix their history.”[3]

Heads up

The practical test takes two seconds. Before you rebase, ask: has this branch ever left my machine in a form someone else could have pulled? If yes, do not rebase it. If it has only ever lived on your laptop, rebase away.

Takeaway

The golden rule collapses to one line: rebase private history, merge shared history. Everything people argue about online is just this rule applied to specific situations.

Interactive Rebase: The Part You Actually Wanted

Here is the thing nobody tells you up front. Most of the time you reach for rebase, you don't care about avoiding a merge commit. You care about cleaning up your own messy commits before a reviewer sees them. That's interactive rebase, and it is the feature worth learning rebase for.

You've been there. Your branch has commits like “wip,” “fix,” “actually fix,” “typo,” and “fix the fix.” Nobody wants to review that. Run git rebase -i HEAD~5 to open the last five commits in an editor, and Git hands you a todo list where you rewrite your own history line by line.[3]The six commands you'll actually use:

  • pick keeps the commit as-is. This is the default on every line.
  • rewordkeeps the commit but lets you rewrite its message. For when the code is fine but the message is “asdf.”
  • squashfolds this commit into the one above it and lets you combine the messages. Five “wip” commits become one real commit.
  • fixupis squash's quieter sibling: it folds the commit in but throws the message away, keeping only the message above.
  • edit stops the rebase at that commit so you can amend the actual files, then continue. For splitting a giant commit into smaller ones.
  • drop deletes the commit entirely. Or just delete the line, same effect.

Reorder the lines and the commits reorder. Change pick to squash on the four junk commits and they collapse into the first one. Save, close the editor, and your branch is now a tidy series of commits that reads like you knew what you were doing the whole time. The workflow that makes this safe is the golden rule again: you do this before you push, on commits only you have.[1]If you've already pushed, cleaning up means a force-push, and the only civilized way to do that is git push --force-with-lease, which refuses to clobber the remote if someone else pushed in the meantime. Plain --forcewill happily flatten a teammate's work. Don't use it.

The Team Workflow Debate, and Where I Land

Ask “should our team rebase or merge” in any engineering channel and you'll get a religious war followed by someone saying “it depends.” I hate that answer. It depends is a way of avoiding a stance. So here is mine.

Rebase your own branch to clean it up. Merge it into main. That's the default, and it's not a compromise, it's the actual best answer for most teams. Pro Git calls this getting “the best of both worlds: rebase local changes before pushing to clean up your work, but never rebase anything that you've pushed somewhere.”[2] You use interactive rebase privately so each branch arrives as a clean story. Then you merge that branch into main so the shared history is never rewritten and nobody gets the golden-rule treatment.

The people who insist on a perfectly linear mainwith zero merge commits, usually enforced by squash-merging every pull request, aren't wrong exactly, and plenty of great teams run that way. A linear log is genuinely easier to read and to bisect. But be honest about the cost: squash-merging throws away the individual commits inside a branch, so all that careful interactive-rebase work you did gets flattened into one commit anyway. If your team squash-merges, don't bother polishing intra-branch history, the polish gets deleted on the way in.

The one position I'll argue against flatly: teams that rebase shared branches to keep things “clean.” That's not clean, it's a foot-gun aimed at your coworkers. Cleanliness on a branch other people pull is not worth a single afternoon of someone reconstructing their work by hand.

Rebase is a scalpel for your own history and a chainsaw for everyone else's. Same tool, and the difference is entirely who else is holding the branch.

What I'd Actually Do

Keep the two pictures in your head and you never have to memorize rules again, you just read them off the picture. Merge writes a new commit that joins two histories and touches neither. Rebase replays your commits on top of newer code and gives them new IDs. Because rebase gives them new IDs, you only ever do it to commits nobody else has, which is the entire golden rule.

My concrete habit: on a personal feature branch, I rebase onto main freely to stay current, and I run git rebase -ibefore opening a pull request to squash the junk and fix the messages. Once that branch is pushed and someone's reviewing it, I stop rebasing and let it merge in. That's the whole discipline, and it's the same shape as a lot of good engineering: move fast and rewrite freely in private, then be conservative and additive the moment other people depend on your work. If you're newer to the toolchain, it pairs well with understanding how your build and runtime environment is layered, because both are really about knowing which layer is safe to change and which one other people are standing on.

Primary sources

  1. 1.PrimaryAtlassian, "Merging vs. Rebasing" Git tutorial. Canonical statement of the golden rule of rebasing, the local-cleanup workflow, and the "is anyone else looking at this branch" test.
  2. 2.PrimaryPro Git (2nd ed.), "Git Branching, Rebasing". Rebase-as-replay definition, three-way merge mechanics, the exact golden-rule sentence, and the "best of both worlds" recommendation to rebase local work but never rebase what you have pushed.
  3. 3.PrimaryGit reference manual, "git-rebase". Interactive rebase todo-list commands (pick, reword, edit, squash, fixup, drop) and the explicit warning that rebasing a branch others have based work on forces downstream developers to fix their history by hand.

Frequently asked questions

What is the difference between git rebase and git merge?
The core difference is that git merge preserves both histories and ties them together with a new merge commit, while git rebase rewrites your branch so its commits replay on top of the other branch as a straight line with no merge commit. Merge leaves a record showing the branches developed in parallel and then came back together. Rebase moves your branch to start from the tip of the other branch, then replays your commits one by one on top, so the history looks like you never diverged.
Is rebase better than merge?
Neither is better in the abstract; they solve different problems, and the right answer is to use both. Rebase is for cleaning up your own local work before anyone sees it, because it produces a linear, readable history. Merge is for combining a finished branch into a shared branch like main, because it never rewrites commits other people already have. The trouble only starts when people use rebase on shared commits, which is exactly what the golden rule tells you not to do.
What is the golden rule of rebasing?
The golden rule of rebasing is to never rebase commits that exist outside your own repository and that other people may have based work on. Rebasing rewrites commit history, so if you rebase a branch someone else has already pulled, their copy and yours no longer share the same commits, and Git can no longer reconcile them cleanly. In practice this means: rebase your private local branch all you want, but never rebase main, a shared feature branch, or anything you have already pushed for review.
Does rebasing delete commits or lose work?
Rebasing does not delete your work; it creates new commits with new IDs that contain the same changes, and the original commits stay in your reflog for weeks in case you need them back. What rebase does destroy is the old commit history, meaning the exact hashes and the branching shape. That is why it is safe on private branches and dangerous on shared ones: your local machine can find the replaced commits with git reflog, but a teammate who pulled the old versions cannot.
When should I use interactive rebase?
Use interactive rebase (git rebase -i) to clean up your own commit history before you open a pull request. It lets you squash five messy "wip" commits into one clear commit, reword a bad commit message, reorder commits, or drop a commit you no longer want, all before a reviewer ever sees them. Run it only on local commits you have not shared yet, because it rewrites history and falls squarely under the golden rule.

Written by

Tech Talk News Editorial

Computer engineering background. Writes about software, AI, markets, and real estate, and the places where the three meet.

More about the author
ShareXLinkedInRedditEmail