GitBeginner

Git Rebase vs. Merge: When to Actually Use Each

A clear, practical guide to choosing between git rebase and git merge — no dogma, just tradeoffs and real workflows.

DevFieldGuideJune 14, 2026 (updated July 16, 2026)6 min read
Share:

Every team eventually has the rebase-vs-merge argument. Both commands solve the same problem — combining diverging branches — but they leave very different history behind.

What each command actually does

git merge creates a new commit that ties two branches together, preserving both histories exactly as they happened.

bash
git checkout main
git merge feature/login

git rebase replays your branch's commits on top of another branch, rewriting commit hashes in the process.

bash
git checkout feature/login
git rebase main

The tradeoff in one sentence

Merge preserves true history at the cost of a messier graph; rebase produces a clean, linear graph at the cost of rewriting history.

AspectMergeRebase
HistoryPreserves exact history, including a merge commitRewrites commit hashes to replay changes linearly
Graph shapeBranches and merges — shows real historyClean, straight line — reads like it happened sequentially
Safe on shared branches?Yes — never rewrites what others haveNo — breaks anyone who already pulled the old commits
Typical useLanding a feature branch into main via PRCleaning up your own local commits before opening a PR

When to merge

  • Merging a feature branch into main via a pull request — keep the merge commit as a record of when the feature landed.
  • Any branch that other people have already pulled and built on top of. Rewriting shared history breaks their local branches.

When to rebase

  • Cleaning up your own local commits before opening a pull request (git rebase -i).
  • Keeping a long-lived feature branch up to date with main without a "merge main into feature" commit on every sync.
bash
git fetch origin
git rebase origin/main

The golden rule

Never rebase a branch that others have already pulled from, unless the whole team has agreed to force-push and re-sync. Rebasing rewrites commit SHAs — anyone with the old commits will get conflicting history.

A sane default for most teams

  • Rebase locally to keep your own commits clean.
  • Merge (often via a "squash and merge" PR) when landing into a shared branch.

That combination gives you a readable personal workflow and a stable, non-destructive shared history.

Rebasing cleanly is one habit; automating the rest of the pre-commit checklist with Git hooks is the complementary one — together they keep history both clean and actually correct before it ever reaches a shared branch.

Squashing commits before opening a PR

git rebase -i isn't just for replaying onto another branch — its most common day-to-day use is cleaning up your own commit history before anyone else reviews it:

bash
git rebase -i HEAD~5

This opens an editor listing the last 5 commits, each prefixed pick. Changing a line's prefix to squash (or s) merges that commit into the one above it, letting five "wip", "fix typo", "actually fix it" commits become one clean, reviewable commit before a teammate ever sees the history:

pick a1b2c3d Add login form squash e4f5g6h wip squash h7i8j9k fix typo squash k1l2m3n actually fix it pick n4o5p6q Add tests

The two pick commits stay separate; the three squash commits collapse into the first pick above them, prompting for a combined commit message. This is entirely local history rewriting — safe on a branch nobody else has pulled yet, which is exactly the golden rule from above.

Rewriting just the last commit

For the narrower case of fixing only the most recent commit (a typo in the message, or a small missed change), git commit --amend is simpler than a full interactive rebase:

bash
git add forgotten-file.ts
git commit --amend --no-edit

--no-edit keeps the existing commit message; omit it to open the editor and change the message too. Like any history rewrite, this changes the commit's SHA — the same force-push caveat from the golden rule applies if it's already been pushed.

Reordering and editing older commits

Interactive rebase isn't limited to squashing — changing pick to edit on any commit in the list pauses the rebase right after that commit is applied, letting you amend it (add a forgotten change, split it into two commits) before continuing:

bash
git rebase -i HEAD~5
# change 'pick' to 'edit' on the commit to modify
bash
# rebase pauses here, on that commit
git add fix.ts
git commit --amend --no-edit
git rebase --continue

Reordering the lines in the interactive rebase editor before saving also reorders the commits themselves, replaying them in whatever sequence you arranged — useful for grouping related changes together in the final history even if they weren't made in that order originally.

Common mistakes

Common mistakes
  • Rebasing a branch that a teammate has already pulled and built on top of. Their local history now conflicts with the rewritten one, and reconciling it is more disruptive than whatever the rebase was meant to clean up.
  • Using git push --force after a rebase instead of git push --force-with-lease. Plain --force will happily overwrite commits a teammate pushed after your last fetch; --force-with-lease refuses if the remote moved since you last saw it.
  • Resolving a rebase conflict by blindly accepting "theirs" or "ours" without reading the diff — during a rebase, "ours" and "theirs" are reversed from what most people expect (relative to the target you're rebasing onto, not your branch), which leads to silently reverting the wrong side.
  • Rebasing to "clean up history" on a branch that's about to be squash-merged anyway. If the PR merge strategy already squashes to one commit, an interactive rebase to tidy commits first is often wasted effort.

Handling rebase conflicts

Best practices
  1. When git rebase stops on a conflict, resolve the conflicting file(s) exactly as you would in a merge, then stage them with git add.
  2. Run git rebase --continue to move to the next commit in the replay.
  3. If a specific commit turns out to be unnecessary once conflicts are resolved, git rebase --skip drops just that commit and continues.
  4. If it's gone wrong, git rebase --abort returns you to exactly the state before the rebase started — there's no partial-state risk to worry about.
Advertisement

Frequently Asked Questions

Advertisement
DevFieldGuide
DevFieldGuide

Editorial Team

Practical tutorials and developer tools, written and maintained by the DevFieldGuide team.

Enjoyed this article?

Get the next one straight to your inbox, along with the best of what we publish each week.

Related Articles

More in Git

View all