The merge with one parent
Open a pull request on a repository you don't administer and there is a decent chance the green button offers you exactly one thing: Squash and merge. No dropdown, no caret, no alternative. It reads like GitHub renamed something.
They didn't. That string has been on that button since April 1, 2016, and it has not changed once in the decade since. What changed is the dropdown next to it, and the reason it's gone is more interesting than a rename would have been.
What the button actually does
Not a merge. Not in any sense git's object model recognizes.
A real merge produces a commit with two parents. That second parent is the
entire point -- it's a permanent record that says these two lines of
history are now one, and every later operation reads it. git merge
consults it to know what's already been applied. git log --graph draws
it. git branch --merged answers from it.
A squash merge produces a commit with one parent, on the base branch,
whose tree is the same tree a real merge would have produced. The diff
survives; the topology doesn't. Your branch's tip is not an ancestor of
anything. As far as the graph is concerned, that branch was never merged
into anything -- a stranger arrived on main one day carrying an identical
set of changes, and the resemblance is a coincidence.
Git is admirably honest about this, and the honesty predates GitHub by
years. git merge --squash computes the merge, stages the result, and then
deliberately declines to finish the job: it doesn't commit, doesn't move
HEAD, and specifically does not record MERGE_HEAD. That last omission
is the whole feature. MERGE_HEAD is what tells the next git commit to
write a second parent, so leaving it out guarantees the commit comes out
single-parented. The plumbing refuses to let you pretend.
"Squash" is precise. "Merge" is marketing.
The verb itself comes from the same place a lot of git vocabulary does --
somebody needed a word. Interactive rebase adopted squash as a todo-list
keyword for folding one commit into its predecessor, which is where most
people meet the term first, and the two senses have been reinforcing each
other ever since.
How it went from an option to the option
GitHub shipped the button in 2016 with a pitch about keeping history tidy
and easier to digest -- that the base branch shouldn't have to carry
oops missed a spot forever. It was presented as one of three ways to land
a pull request, which is what it was.
The path from there to a button with no dropdown runs through settings, not through the UI:
Repository settings. Three checkboxes -- allow merge commits, allow squash merging, allow rebase merging. Tick more than one and collaborators choose at merge time. Tick exactly one and there is nothing to choose, and the button stops looking like a menu. This has been there approximately forever, and it's the mechanism behind most single-option buttons you've ever seen.
Rulesets. In December 2024 GitHub previewed a pull request merge method rule, and in March 2025 it went generally available at the repository and organization level. This is a different kind of thing from a checkbox. A ruleset targets branches by pattern, so the policy can be "squash into the default branch, rebase into feature branches" -- a rule about where a change is going rather than a property of the repo. And it's administered from above: one org-level ruleset covers every repository under it, including the ones created next year.
Reach. In June 2025 organization rulesets came to Team plans. That's the step that matters for how often you see this. Enforcement stopped being an enterprise-tier feature and became something a five-person shop turns on in an afternoon.
So the phrase migrated. It used to be a verb -- a thing a person did, at merge time, having thought about it. It's now a noun that lives in a config file:
merge_method: squash
Nobody at merge time is deciding anything. Somebody decided in March, for everyone, for every repository, and what's left on the button is the residue of that decision. That's why it reads like a product change. In a sense it is one -- just not GitHub's.
What you're trading
The case for it is real and worth stating properly, because most arguments about this are conducted between people who have never had to maintain the other side's history.
main becomes one commit per reviewed change. Not one commit per
keystroke somebody happened to save. git log --oneline on the base branch
is a list of things that were actually discussed, and each entry links back
to the pull request where the discussion is.
Revert is one revert. git revert <sha> and the change is gone. No
-m 1, no reasoning about which parent was the mainline, no discovering
that four of the branch's eleven commits were also cherry-picked elsewhere.
Bisect steps are units that were green. This is the underrated one. The
intermediate commits on a feature branch were mostly never tested
individually -- CI ran on the merge result, not on commit 6 of 11. A history
made of squashed pull requests is a history where every step actually
passed something, which is exactly the property git bisect assumes and
almost never gets.
Against that:
Git can't tell that the changes landed. The branch tip isn't an ancestor of the base, so nothing in git knows those changes are already applied. Merge the branch again later and every conflict comes back, in full, against code that already contains the resolution. For a short-lived branch deleted on merge, this costs nothing. For a long-lived branch, a release branch, or a fork other people also pull from, it's the sharp edge -- and it stays sharp forever, because there's no record to consult.
Blame gets coarser in proportion to the squash. Twelve commits with
useful messages become one commit whose message is a pull request title.
git blame on a line inside a 2,000-line squash tells you the change
happened; it can't tell you which part of the change it belonged to. The
same bisect that got more reliable also got less precise: a bisect that
lands on a squashed commit has narrowed the bug down to an entire feature.
Authorship needs a trailer. A squash commit has one author. If two
people worked on the branch, the second one exists only if somebody wrote
Co-authored-by: into the message -- which GitHub will do for you, from the
squashed commits, if the message template hasn't been overridden. Plenty
have been.
What this repo does
This site keeps real merges. pull.rebase false, and the history has
sixteen merge commits in it, most of them the standard
Merge pull request #N from japherwocky/.... The branches are visible; you
can see that notes/agents-md-writeup was a thing that existed, and when
it came home.
That's not a recommendation, it's a different set of constraints. This is a
one-person repository where nobody is reading main's log to reconstruct
what shipped, and where nothing is gained by pretending the branches didn't
happen. The squash argument gets stronger with every additional person, and
strongest at the point where the log stops being a diary and starts being
documentation somebody actually consults.
Which is the honest summary of the whole thing. Squash merging trades information git can use for information humans can use, and every reasonable position on it is really a claim about who the audience is. The argument only sounds settled right now because on a lot of repositories somebody upstream settled it, in a ruleset, and the button stopped asking.