linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
Intro
Lessons
Footer
linuxlab-TutorialsPricingAboutPrivacy & cookies
Copyright © 2026 LinuxLab. All rights reserved.
linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
  • Introduction
  • Chapters
  • How it works
  • Lessons
  • Knowledge base
  • Interview prep
home/git/kb/Collaboration/merge-strategies

kb/collab ── Collaboration ── intermediate

PR merge strategies (GitHub)

GitHub offers three buttons to merge a PR: Create a merge commit (--no-ff, with a merge commit), Squash and merge (one squashed commit with no parent from the branch), and Rebase and merge (rebase + fast-forward with no merge commit). Teams pick one for the whole project.

view as markdownaka: merge-strategy, github-merge-buttons

When a PR is ready to merge, GitHub offers three strategies. These are not different Git commands but three ways to integrate a branch. GitLab and Bitbucket offer the same options under slightly different names.

Create a merge commit

Equivalent to git merge --no-ff feature. A merge commit with two parents is created even when a fast-forward would be possible.

main:  ... -> A -> B -> M  <- merge commit
                   \ /
             feat:  C -> D

Advantages:

  • History preserves the fact that a branch existed. You can see where the feature lived.
  • The PR can be reverted with one command: git revert -m 1 <merge-sha>.
  • All PR commits land in main as-is.

Disadvantages:

  • History fills up with merge commits, especially on an active project.
  • Linear navigation is harder (git log --first-parent helps).

When to choose: large teams focused on auditing and rolling back entire PRs; teams that value transparency about where changes came from.

Squash and merge

GitHub takes all PR commits, squashes them into one new commit, and appends it to main with no merge commit.

main:  ... -> A -> B -> S    <- S contains all changes from feat

The original branch commits do not land in main (they remain in the branch until it is deleted, then accessible via reflog for a while).

Advantages:

  • Main history is always linear and clean.
  • One PR equals one commit; granularity matches tickets.
  • Internal PR noise (WIP, fix typo, address comments) does not land in main.
  • Rolling back a PR is a plain git revert <commit-sha>.

Disadvantages:

  • Atomic commits inside the PR (if the author cleaned them up) are lost.
  • For bisecting inside a feature you have to go back to the branch itself; main has only one commit for the whole PR.
  • The connection between a commit in main and the PR branch exists only through the commit message (if (#123) was added automatically).

When to choose: small teams that value a clean linear history and where PR authors are not disciplined about commits. In practice this is the most common default for commercial projects, though large organizations with strict auditing requirements often prefer merge commit (see below).

Rebase and merge

All PR commits are rebased on top of main (getting new SHAs), then fast-forwarded into main. No merge commit.

main:  ... -> A -> B -> C' -> D'    <- C' and D' are rewritten feat commits

Advantages:

  • Linear history, like squash.
  • Preserves atomic commits inside the PR, like merge commit.
  • Bisect works across the full history, including the internals of each PR.

Disadvantages:

  • Commit SHAs differ from those in the branch after rebase. If anyone referenced SHAs from the feature branch before merge, those references break.
  • Requires the PR author to write clean commits. If commits read "WIP" or "fix," they land in main one by one, which is worse than squash.
  • The "commit to PR" link is lost; you must search by message.

When to choose: teams willing to invest in clean commits via interactive rebase, where both a linear history and preserved atomic commits matter. (Note: the Linux kernel does not use GitHub's "Rebase and merge" button. They use an email and maintainer-tree model. The principle of "linear history plus atomic commits" is the same; the integration mechanism is different.)

Comparison

StrategyMerge commitPreserves PR commitsHistory
Merge commityesyesbranched
Squash and mergenono (one new commit)linear
Rebase and mergenoyes (new SHAs)linear

Which strategy for which team

Practical rules:

  • Startup / small team / no commit discipline → Squash and merge. Covers most scenarios, requires no rebase knowledge, history stays clean.
  • Large company / many teams / auditing matters → Merge commit. Being able to revert an entire PR in one step is worth more than a linear history.
  • Open source / professionals / atomic commits are the norm → Rebase and merge. Preserves the quality of the internal PR history.

The key decision is to pick one strategy for the project. A mix of styles in one history is hard to read: sometimes branches, sometimes linear, sometimes one commit per PR, sometimes ten.

Configuring in GitHub

Settings -> General -> Pull Requests -> Merge button. You can allow one, two, or all three buttons. Leaving only the chosen strategy reduces confusion and prevents "squash today, rebase tomorrow."

Additional settings:

  • Always suggest updating pull request branches: when an update is available, show a button to bring the branch up to the latest main.
  • Allow auto-merge: the PR merges automatically once conditions are met (approve + CI).
  • Automatically delete head branches: delete the branch after merge. Enable this.

Pitfalls

  • Squash and branch protection "require linear history" do not conflict. Squash produces a linear history by definition.
  • Squash and commit metadata. GitHub automatically appends (#123) with a link to the PR. Useful for navigation; verify that it is enabled in settings.
  • Rebase on large PRs. On a PR with 30 commits, rebase can trigger a series of conflicts (one per commit). If main is active, squash is usually better so you resolve the conflict once.

§ см. также

  • mergegit mergeMerges another branch into the current one. Either fast-forwards the pointer or creates a merge commit with two parents. Overlapping changes produce conflicts.
  • rebasegit rebaseRewrites the commits of a branch so they descend from a different commit. Each commit gets a new SHA; history becomes linear. Safe only on branches that no one else has seen.
  • pull-requestPull Request (PR)A request to merge a branch into the main branch after passing review and CI. On GitHub/GitLab/Bitbucket it is the standard mechanism for collaborative work. Technically it is not a Git command but a hosting feature built on top of branches and commits.
Footer
linuxlab-
Copyright © 2026 LinuxLab. All rights reserved.
Tutorials
Pricing
About
Privacy & cookies