Skip to content

Rebase vs Merge

Your feature branch and main can both advance after they split. Before opening or completing a pull request, you may need the newer main changes on your feature branch. Merge and rebase solve that problem differently.

A──B──C main
└──F1──F2 feature/login

B is the shared ancestor. C was added to main; F1 and F2 were added to the feature branch. Neither tip is an ancestor of the other, so simply moving a branch label forward cannot combine them.

Option 1: merge main into the feature branch

Section titled “Option 1: merge main into the feature branch”
Terminal window
git switch feature/login
git fetch origin
git merge origin/main
A──B──C─────────┐ main ends at C
└──F1──F2──M feature/login ends at M

M is a new merge commit with two parents: F2 and C. The existing commit objects keep their identities. The graph records when the two lines came together. This is a good default when commits have already been shared or preserving the branch’s development history matters.

Fetching first only updates origin/main, your local view of the remote branch. It does not move local main or your feature branch. The subsequent merge is the integration step.

Terminal window
git switch feature/login
git fetch origin
git rebase origin/main
A──B──C──F1′──F2′ feature/login
└ main

Git finds the commits on the feature branch since the common ancestor, then replays their changes onto C. The resulting F1′ and F2′ are new commit objects with new hashes: their parents changed. The originals may remain temporarily recoverable through the reflog, but the branch now points to the replayed commits. Rebase gives a linear history; it does not magically combine both histories without rewriting the feature commits.

When you later merge this rebased feature into an unchanged main, a fast-forward is possible. Whether the hosting platform creates a merge commit, squashes, or rebases at pull-request completion depends on the chosen merge method and repository rules.

Git pauses while replaying the conflicting commit. Inspect the files, choose the correct final content, remove conflict markers, and stage the resolved files:

Terminal window
git status
git add path/to/resolved-file.cs
git rebase --continue

Repeat for each conflict. If you need to return to the pre-rebase state instead:

Terminal window
git rebase --abort

Do not run git rebase --continue before resolving and staging the conflict. Run the project tests after the replay: individually valid commits may interact differently with the updated base.

Situation Usually choose Why
Updating a local, unpublished feature branch Rebase or merge Rebase can keep the history linear; merge preserves the original graph
Updating a branch other people use Merge Rebase changes commit identities they may already have
Integrating an approved pull request Repository’s PR merge policy The team may require merge, squash, or rebase merge
Keeping a detailed record of integration points Merge The merge commit records the join

Never casually rebase shared main or another shared branch. If a feature branch was already pushed, a rebase will normally make an ordinary push fail because the remote still points to the old history. On a branch that only you own, after checking nobody else depends on it and after coordinating around an open pull request, you may use:

Terminal window
git push --force-with-lease origin feature/login

--force-with-lease refuses the update if the remote branch moved since your last observation; it is safer than plain --force, but it still rewrites that remote branch and can disrupt collaborators or invalidate review context. Never use it to bypass protection on shared main.

Your feature/login branch adds a .NET authentication endpoint. Meanwhile, main changes the user entity. Fetch first. If your branch is yours alone, rebasing onto origin/main can let you adapt the endpoint to the new entity before the pull request. If teammates also use the feature branch, merge origin/main into it instead. In either case, run dotnet test and push the updated feature branch for CI and review.

  • Merge adds a join commit when histories diverged and preserves existing commits.
  • Rebase replays feature commits on a new base, producing new hashes.
  • Conflicts are possible with either method; a linear graph is not proof that the code works.
  • Avoid rewriting shared history. Use the repository’s PR policy for the final integration.
  1. Why does F1 get a new hash after rebasing onto C?
  2. Which method would you normally use if teammates have already based work on your feature branch?
  3. What is the difference between git rebase --abort and git rebase --continue?

Git rebase reference · Git merge reference