Merge vs rebase vs squash: when to use which

Status: đźź© COMPLETE Last updated: 2026-06-21 Plain-English tagline: Three ways to combine Git branches. They produce different histories with the same end state. Pick by where you are in the workflow.


What this decides

When you have changes on one branch and want them in another, Git offers three integration strategies:

  • Merge — keep both histories, add a “merge commit” that joins them
  • Rebase — replay one branch’s commits onto the other’s tip; linear history
  • Squash — collapse all of one branch’s commits into one commit on the other

For the textbook: Branches & merging đźź©, Rebase vs merge đźź©.


The short answer

Defaults for solo developers and small teams:

SituationUse
Merging a finished PR into mainSquash (cleanest main history)
Catching up your feature branch with main mid-workRebase (no merge commits in your branch)
Combining long-lived team branchesMerge (preserves shared history)
Polishing messy commits before opening a PRInteractive rebase (git rebase -i)

If you’re solo on Bible Quest, squash-merge for PR merges + rebase to update your branch is the right default. That’s what the playbook recommends.


The factors that matter

  1. Is the branch shared? If others have based work on your commits, rewriting history (rebase/squash) breaks them. Use merge.
  2. Do you value linear history? Squash and rebase produce linear graphs. Merge preserves branching shape.
  3. Do individual commits have intrinsic value? Yes → preserve them (merge or rebase). No → squash them away.
  4. How easy do you want reverts to be? Squash makes “revert this PR” = one commit revert. Merge/rebase requires reverting multiple commits.
  5. Does your team have a convention? Don’t be the person who breaks it.

When to pick MERGE

  • The branch is shared. Multiple developers have based work on it. Don’t rewrite history.
  • The branch has a meaningful structure you want preserved in main’s history. (E.g. a long-running refactor where each commit was its own milestone worth seeing.)
  • You’re integrating two parallel long-lived branches (e.g. develop → main). The merge commit marks the integration point.
  • You want a permanent record of “this branch existed.” Some teams use merge commits as audit markers.

Use in Git:

git switch main
git merge feature/x

GitHub UI: “Create a merge commit” option.


When to pick REBASE

  • You’re solo on the branch (not shared yet).
  • You want to update your feature branch with main’s recent changes without creating a merge commit in your branch’s history.
  • You want a clean, linear PR diff — only your changes, no merge commits cluttering.
  • You’re cleaning up messy commits before opening a PR (interactive rebase: git rebase -i HEAD~5).

Use in Git:

# Update your feature branch with main's recent changes:
git switch feature/x
git rebase main
git push --force-with-lease
 
# Clean up commits before opening a PR:
git rebase -i HEAD~5

GitHub UI: “Rebase and merge” option (for PR merge — replays branch commits onto main without a merge commit).

Critical: never rebase commits that other people have based work on. Use rebase on your private branch only.


When to pick SQUASH

  • Merging a PR into main. Most modern teams default to this.
  • The branch had messy intermediate commits that no one needs to see (“WIP”, “fix typo”, “actually fix”).
  • You want main’s history to read as a sequence of features, not a flood of small commits.
  • You want easy revertability — one commit per PR makes “revert this feature” a one-shot.

Use in GitHub UI: “Squash and merge” button on the PR. The PR description becomes the squashed commit message.

On the command line (rare — usually done via PR UI):

git switch main
git merge --squash feature/x
git commit -m "Add feature X"

Combining strategies (the typical workflow)

A common, healthy pattern for a feature:

  1. Branch off main: git switch -c feature/x
  2. Work, commit frequently — messy commits are fine
  3. Main moves: rebase your branch to stay current — git rebase main
  4. Clean up commits before opening a PR — git rebase -i HEAD~5 (squash WIP, reword, drop)
  5. Open PR
  6. Reviewers comment; push fixes — small follow-up commits OK
  7. Merge via GitHub’s “Squash and merge” button — one clean commit on main, your PR description becomes the message

This is the Bible Quest workflow. Squash-merge is the default; rebase is the in-branch tool; merge is rarely used.


The golden rule of rebasing

Never rebase commits that have been pushed to a shared branch.

If you rebase commits that others have pulled, their copies and yours diverge. When they next try to pull, they’ll fight a merge conflict for every commit you rewrote.

Safe to rebase:

  • Your local branch, not yet pushed
  • Your branch, pushed but only you work on it (force-push with --force-with-lease)

Don’t rebase:

  • Any branch others have based work on
  • Shared branches (main, develop)
  • Branches with active PR comments referencing specific commit hashes

What if I’ve already chosen?

“I squashed but I wish I’d kept the commits”: the commits still exist in your local Git for ~90 days (reflog). After that they’re gone. Squash decisions are practically permanent.

“I rebased and broke a teammate’s work”: they need to git reset --hard origin/branch and lose any commits that weren’t shared. Hopefully it’s recoverable from their reflog.

“I merged with a merge commit and wish I’d squashed”: you can revert the merge and re-merge with squash, but the noise is rarely worth it. Just let it sit.

“My team’s default is merge but I want squash”: raise it in a retro. Don’t unilaterally change practice — Git workflow conventions need team buy-in.


See also


Sources