skip to content

questions

6

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

open as a page

A git rebase stops on a conflict — what do --continue, --skip, and --abort each do?

level: middleimportance: must knowfreq 58%

basics

~20 s

After you stage a resolution, git rebase --continue records that commit and resumes the replay. git rebase --skip discards the commit being replayed entirely and moves on. git rebase --abort ends the whole operation and returns the branch to its pre-rebase tip.

open as a page

Why does git rebase give every replayed commit a new SHA even when the content is identical?

level: middleimportance: must knowfreq 65%

basics

~20 s

A commit's hash is computed over its whole content, which includes its parent, its message, and both author and committer identity and timestamp. Rebase re-creates each commit with a different parent and a fresh committer timestamp, so the hash must differ.

open as a page

What does git rebase --onto main feature-a feature-b do, and when do you need it?

level: middleimportance: should knowfreq 45%

basics

~20 s

It replays the commits reachable from feature-b but not from feature-a onto main, then moves feature-b to the result. You need it when the commits you want to move and the base you want to cut them from are different things.

open as a page

What problem does git rebase --update-refs solve when you stack dependent branches?

level: seniorimportance: should knowfreq 25%

basics

~20 s

When branches point at intermediate commits in a stack, rebasing the top branch normally leaves those refs on the old, pre-rebase copies. The --update-refs option moves them to the corresponding replayed commits so the whole stack stays consistent.

open as a page

In a Git repo, what are the real costs of requiring every branch to be rebased before landing?

level: principalimportance: should knowfreq 32%

basics

~20 s

A linear history buys readable logs and simpler bisecting, but every rebase copies commits: conflicts are re-resolved per commit and per rebase, shared branches need coordinated force-pushes, intermediate commits are combinations that were never tested, and old hashes recorded elsewhere stop resolving.

open as a page