In GitHub, what does the Require linear history branch rule actually prevent?
answer
- it is a constraint on commit shape
- how many parents may a commit have
- one of three merge buttons dies
- squash and rebase survive
- named required_linear_history in rulesets
basics
~10 sIt rejects any commit with more than one parent landing on the branch. Practically, the merge-commit button is unavailable on that branch: only squash merge and rebase merge can produce commits GitHub will accept.
solid answer
~40 s"Require linear history" is a rule on the target branch that refuses any update introducing a **merge commit** — a commit with two or more parents. It is a shape constraint on the result, not an instruction about how you work: you may still merge the base into your pull request branch as often as you like while developing, because those commits are on your branch, not on `main` yet. What it removes is a landing option. Of GitHub's three merge buttons, *Create a merge commit* produces exactly the forbidden shape, so on a linear-history branch only *Squash and merge* and *Rebase and merge* remain usable, and teams normally also switch the disallowed method off in repository settings so nobody is offered a button that will fail. In rulesets the same rule is `required_linear_history`.
code
json · 13 lines{
"name": "protect-main",
"target": "branch",
"enforcement": "active",
"conditions": {
"ref_name": { "include": ["refs/heads/main"], "exclude": [] }
},
"rules": [
{ "type": "required_linear_history" },
{ "type": "non_fast_forward" },
{ "type": "deletion" }
]
}go deeper
Recall that a merge commit has more than one parent and that this rule refuses those on the protected branch, leaving squash and rebase as the ways a pull request can land.
Explain that the rule constrains the resulting commit shape rather than your workflow, and pair it with the repository's allowed merge methods so the offered button matches what the rule accepts.
Weigh the readability and revert story of a linear default branch against the loss of authored history, and check the rule against a merge queue's configured merge method before blaming the queue.
Own the history policy for the organization: whether linear history is mandated everywhere via an org ruleset, what it implies for auditability and release notes, and what exceptions you will tolerate.
## The rule in one sentence A branch with "Require linear history" enabled will not accept an update whose new commits include any commit with more than one parent. That is the whole rule. Everything else people believe about it — that it forces rebasing, that it bans merging, that it requires squashing — is a consequence of that single shape constraint, or a misunderstanding of it. ## Why anyone wants it A linear default branch has one property teams value: the first-parent history is the complete list of landed changes, in landing order, and every commit on it is a state the branch actually passed through. That makes `git log` readable without graph gymnastics, makes bisecting straightforward, and makes "what shipped between these two points" a simple range. The cost is that the individual authoring history of each change is either flattened (squash) or replayed onto the tip (rebase), so the exact commits the author wrote are not what the branch records. ## What it does to GitHub's merge buttons GitHub offers three ways to land a pull request, and the repository's settings decide which are available at all: - **Create a merge commit** — produces a commit with two parents (the base tip and the PR head). This is precisely the shape the rule forbids, so it cannot be used on a linear-history branch. - **Squash and merge** — collapses the pull request into a single new commit with one parent on the base. Always legal under the rule. - **Rebase and merge** — replays the pull request's commits onto the base tip; every resulting commit has one parent. Also legal. So the rule does not "choose squash for you"; it eliminates one option and leaves the team to pick between the other two. Because a disabled-by-rule button is a confusing user experience, the usual configuration pairs the rule with the repository's *Pull Requests* settings: untick **Allow merge commits**, leave squash and/or rebase ticked. The rule is the enforcement (it also covers pushes, not just merges); the settings are the ergonomics. ## What it does not do - **It does not forbid merging inside your branch.** Merging `main` into your feature branch creates a merge commit on the *feature* branch. Whether that ever reaches the protected branch depends on the landing method: squash collapses it away, rebase replays only your own commits. A merge-commit landing would carry it in, which is exactly why that button is gone. - **It does not require an up-to-date branch.** Freshness against the base is the separate "require branches to be up to date" condition on required status checks. - **It does not prevent force pushes.** Blocking history rewrites is the separate rule (`non_fast_forward` in rulesets). A linear branch can still be rewritten unless you block that too, and a linear-history rule with force pushes allowed is a fairly weak guarantee about what the branch's history means. - **It does not apply retroactively.** Merge commits already in the branch's history stay there; the rule is evaluated on new updates only. ## Interaction with other platform features A merge queue is compatible with linear history: the queue merges entries using the configured merge method, so pick squash or rebase for that branch. If a repository requires linear history but has left merge-commit as the queue's method, entries will fail to land — a small configuration trap worth checking when a queue mysteriously cannot merge anything. Revert pull requests are also worth a thought. GitHub's *Revert* button opens a pull request containing a revert commit, which is an ordinary single-parent commit and lands fine under the rule. Reverting a *squashed* pull request reverts the whole change as one unit, which is usually what you want and is one of the practical arguments for squash on a linear branch. ## Configuring it In classic branch protection it is a checkbox on the rule. In a ruleset it is a rule object of type `required_linear_history` in the ruleset's `rules` array, which means an organization can apply it to many repositories at once by targeting branch-name patterns, and can see it listed alongside every other rule that applies to the branch. ## Interview framing Define the rule by the commit shape it rejects, then translate that into the concrete effect people feel: the merge-commit button disappears, squash and rebase remain, and repository settings should be aligned so nobody is offered a button that cannot work. Adding that it is orthogonal to force-push blocking and to base freshness shows you are not lumping all branch rules into one blur.
- Does the rule stop you merging main into your own feature branch?No. Those merge commits live on your feature branch, which is not protected. Whether one ever reaches the protected branch depends on how the pull request lands: squash collapses everything into one commit and rebase replays your commits singly, so both stay legal. Only the merge-commit button would carry the forbidden shape across.
- A repository requires linear history and its merge queue cannot land anything. What would you check first?The merge method configured for the queue. A queue set to create merge commits produces exactly the two-parent shape the branch rejects, so entries pass their checks and then fail to land. Switching the queue to squash or rebase resolves it.
- Does requiring linear history clean up merge commits already in the branch's history?No. The rule is evaluated on incoming updates only, so existing merge commits remain. Removing them would require rewriting history, which is a separate and disruptive operation and is usually blocked by the force-push rule on the same branch.
saying these in an interview costs you the question
- Says the rule forces everyone to rebase their local work
- Thinks it also blocks force pushes to the branch
- Believes it rewrites existing merge commits in history
- Claims it means the branch must be up to date with the base
- Confuses it with the repository setting that hides merge buttons