skip to content

In Git, what is the difference between merging main into your branch and rebasing onto it?

level: juniorimportance: must knowfreq 85%

answer

  1. One adds a commit, the other replaces commits
  2. Look at what happens to your existing hashes
  3. Count how many times conflicts can appear
  4. Ask whether the remote will still fast-forward
  5. Copies, not moves

basics

~20 s

Merging adds a new commit that joins both histories and leaves your existing commits untouched. Rebasing re-creates your commits on top of main's tip as new commits with new hashes, producing a straight line with no merge commit.

solid answer

~50 s

`git merge main` while on your branch creates a **merge commit** with two parents — your tip and main's tip. Nothing you already committed changes; the graph records that the two lines of development came back together. `git rebase main` instead replays each of your commits on top of main's current tip, one at a time, creating a **new commit for each** with a new hash. The result is a linear history that looks as though you started from today's main. The trade-off follows from that difference. Rebase gives a history that reads cleanly and reviews as a straight sequence, but it rewrites your commits, so anyone who already has the old ones must reconcile, and you must force-push a branch you had already pushed. Merge preserves exactly what happened and never rewrites, at the cost of a busier graph.

go deeper

for a junior

Be able to state the headline crisply: merge adds a joining commit and changes nothing you already committed; rebase re-creates your commits on a new base with new hashes.

for a middle

Derive the consequences from the mechanism — per-commit conflicts, the force-push requirement, intermediate commits that never existed before — rather than reciting a pros-and-cons list.

for a senior

Show where you draw the line in practice, especially around branches other people have pulled, and how you recover when someone rebases something shared.

for a principal

Own the policy question: what a team gains from a linear log versus a never-rewritten record, and which parts of that should be enforced by convention rather than left to taste.

## Two ways to catch up with a moving trunk You branched off `main` a week ago. `main` has moved on. You need your work to sit on top of that new work before it can land. Git offers two mechanisms with genuinely different semantics. ## Merge: join the histories `git merge main` (while your branch is checked out) computes the merge base — the last commit both branches share — and produces a three-way merge of the two tips. The result is recorded as a **merge commit** with two parents. Crucially, none of your existing commits are altered: their hashes, their contents and their parent links all stay exactly as they were. The history is now a graph with a visible join. Properties worth naming: - Nothing is rewritten, so a branch you have already pushed can be updated with an ordinary push, and teammates who have your branch just fast-forward. - Conflicts are resolved **once**, against the combined state of both tips. - The graph records the true shape of what happened, including the fact that you worked in parallel. - Repeated over many branches, the graph becomes hard to read, and a `git log` without a graph flag interleaves commits from many lines of work. ## Rebase: re-create the commits elsewhere `git rebase main` takes the commits that are on your branch but not on `main` and replays them, in order, on top of `main`'s current tip. Each replay is effectively a cherry-pick: apply that commit's change to the new base and record a new commit. Because a commit's identity is derived from its full content — including its parent and its committer metadata — every replayed commit gets a **new hash**. The originals are not modified; they are simply no longer on the branch, and remain reachable through the reflog until garbage collection. Properties worth naming: - The history is linear. `git log` reads as a sequence, and the branch looks as though it was written against today's `main`. - Conflicts can occur **per replayed commit**, so a ten-commit branch can stop ten times. - Because the commits are new objects, a branch you had already pushed no longer fast-forwards; updating the remote requires a force-push, and anyone who had the old commits must reconcile. - Intermediate commits in the rebased branch are new combinations that never existed before and were never built or tested in that form. ## The rule that follows The long-standing guidance — do not rebase commits that other people have already based work on — is a direct consequence of the copy semantics, not a stylistic preference. Rebasing your own unpushed or personally-owned branch costs nobody anything. Rebasing a branch two colleagues have pulled hands them a divergence they did not ask for. ## Choosing in practice A common, defensible split: rebase your own topic branch while it is in progress, to keep it current and readable; merge when integrating finished work, or whenever the branch is shared. Some teams go further in either direction, and the honest interview answer acknowledges that both are legitimate and the choice depends on how much the team values a linear log versus a never-rewritten record. ## What interviewers listen for A weak answer describes the two commands as different ways to get the same result, or reduces the difference to "rebase is cleaner". A strong answer says: merge creates a commit and preserves history; rebase creates *new copies* of your commits and discards the old ones from the branch; and everything else — the force-push, the per-commit conflicts, the danger on shared branches — follows mechanically from that one fact. Being able to derive the consequences instead of listing memorised pros and cons is the whole signal.

  • Why does rebasing a branch you already pushed require a force-push?
    Because the replayed commits are new objects with new hashes. The remote branch still points at the old commits, and your new tip is not a descendant of them, so the update is not a fast-forward. Git refuses non-fast-forward pushes by default, and you have to explicitly overwrite the remote ref.
  • Why can one rebase stop on conflicts several times when a merge stops at most once?
    A merge produces a single three-way result between two tips, so there is one resolution. A rebase replays commits one at a time, and each replay is its own three-way application against the evolving base, so every commit in the branch can conflict independently.
  • Does rebasing destroy the original commits?
    Not immediately. Rebase creates copies and moves the branch to the new tip; the originals become unreferenced by that branch but remain in the object database and are reachable through the reflog until garbage collection eventually prunes them. That is why an accidental rebase is recoverable.

saying these in an interview costs you the question

  • Says rebase moves commits rather than copying them
  • Claims rebase and merge produce identical history
  • Thinks rebasing a shared branch is safe if nobody complains
  • Believes rebase avoids conflicts altogether
  • Cannot explain where the new hashes come from

context