Rebase vs merge: when to use each

Git has two common ways to integrate work from one branch into another: merge and rebase. Both are useful, but they change history in different ways. The right choice depends on w…

Git has two common ways to integrate work from one branch into another: merge and rebase. Both are useful, but they change history in different ways. The right choice depends on whether you need to preserve branch history, keep a linear history, or avoid rewriting commits that other people may already use.

What merge does

git merge incorporates changes from another branch into the current branch. When the branches have diverged, Git combines the work and records the result, which is usually a merge commit.

A typical merge looks like this:

git switch main
git merge feature/login-timeout

Use merge when you want to preserve the fact that a branch existed and was integrated at a specific point. This is useful for shared branches, release branches, and changes where the branch topology is part of the project record.

Merge does not rewrite the commits that already exist on the merged branch. That makes it safer for shared work.

What rebase does

git rebase reapplies commits from the current branch onto a different base. The replayed commits are new commits with new identities, because their parent history changes.

A typical rebase looks like this:

git switch feature/login-timeout
git fetch origin
git rebase origin/main

Use rebase when you want to update a private topic branch so it appears to start from the current default branch. This can make the final history easier to read, because it avoids unnecessary merge commits from repeatedly updating the branch.

Rebase is also useful in interactive mode when cleaning local commits before review:

git rebase -i HEAD~4

Interactive rebase can reorder, edit, combine, or drop commits before they are shared.

The main difference is history rewriting

Merge adds integration history. Rebase rewrites the commits being replayed.

That difference drives the safety rule: do not rebase commits that other people may already have based work on, unless the team has explicitly agreed to that workflow.

When you rebase a shared branch, everyone else with the old commits must reconcile their local history with the rewritten branch. That creates avoidable confusion and can reintroduce commits that were intentionally changed or removed.

Use merge for shared branches

Use merge when:

  • the branch is shared by more than one person
  • the branch is a release branch
  • preserving the integration point matters
  • the team wants an explicit record of branch joins
  • you are not confident that rewriting the branch is safe

Merge is the conservative default for shared work, because it does not replace existing commits.

For example, a release branch receiving a tested hotfix can be merged back into the default branch:

git switch main
git merge release/2026-06

The merge commit shows that the release line and the main line were brought back together.

Use rebase for private topic branches

Use rebase when:

  • the branch is private to you
  • you want to update the branch on top of the latest default branch
  • you want a linear set of commits before review
  • you want to clean up local commits before pushing
  • your team uses a fast forward or linear history policy

Resolve conflicts commit by commit if they occur. Continue after each resolved conflict:

git add <file>
git rebase --continue

Abort the rebase if the result is not what you expect:

git rebase --abort

Do not use rebase to hide important context

A tidy history is useful, but it should not remove context that matters. Do not squash or rewrite away commits that explain a meaningful sequence of decisions, migrations, or compatibility steps.

Clean history should make the project easier to understand. It should not make a risky change look simpler than it was.

Decide the policy before there is a conflict

Teams should decide their merge policy before a contentious pull request arrives. Common policies include the following.

Squash merge for pull requests

The branch can contain any local commit shape during review. The final merge creates one commit on the default branch. This works well when pull requests are the review unit.

Rebase and fast forward

Every branch is rebased onto the target branch before merge, then fast forwarded. This keeps a linear history but requires discipline around private branches and force pushing.

Merge commits

Every completed branch is merged with a merge commit. This preserves branch topology and makes integration points explicit.

None of these policies is always correct. Pick one that matches the repository, team size, release process, and need for auditability.

Be careful with force push

After rebasing a branch that was already pushed, updating the remote branch usually requires a force push. Prefer the safer form:

git push --force-with-lease

This checks that the remote branch is still in the state your local repository expects before replacing it. It is still a history rewrite, so use it only when rewriting that branch is acceptable.

Conflict handling differs in feel

Merge presents conflicts for the combined integration result. Rebase presents conflicts as Git reapplies each commit, so you may need to resolve related conflicts more than once if several commits touch the same area.

That is not a reason to avoid rebase entirely, but it is a reason to keep commits focused and topic branches short lived.

Conclusion

Use merge when preserving shared history and integration points matters. Use rebase to update or clean private topic branches before they are shared. The practical rule is simple: merge shared work, rebase private work, and choose a repository policy that the whole team follows consistently.