The real cost of requiring linear history Jump to heading

Forges offer a branch protection setting — “require linear history” — that forbids merge commits on a branch. Turn it on and main becomes a straight line: every pull request lands as rebased commits or a single squash commit. The benefits are visible immediately. git log reads top to bottom, bisect never meets a merge, and history looks tidy. The costs are less visible and arrive later: force-pushes become routine, contributors’ commits are rewritten and lose their signatures, pull request context is lost from history, and branches that several people share become awkward. Neither choice is wrong. This page lays out what the rule actually buys and what it costs, so the decision is made deliberately, within merge vs rebase decision matrix.

When to use this approach Jump to heading

  • Someone has proposed enabling “require linear history” on main.
  • The rule is already on, and its side effects — signature loss, force-push friction — are causing trouble.
  • You want to compare linear history with merge commits read through --first-parent.
  • You are writing a team policy, as in writing a team merge policy.

Step 1 — List what linear history buys Jump to heading

The benefits are real and worth stating precisely.

What linear history gives youThe log reads as a single sequence without graph lines. Bisect walks a straight line and never lands on a merge. Every commit on main is one the author or the forge wrote, so blame points directly at a change. Reverting a change is reverting one commit rather than a merge with parent numbers.Readable logno graph linesSimple bisectno merges to testDirect blameline → changeEasy revertno -m parentmost of these can also be had from merge history with --first-parent

The last column of that list is the important part: git log --first-parent, git bisect --first-parent and git blame --first-parent give merge-based history most of the same readability, as shown in reading history with --first-parent. Linear history makes readability the default; merge history makes it an option.

Step 2 — List what it costs Jump to heading

The costs come from the fact that every pull request must be rebased or squashed before it lands.

Linear history against merge commitsRequiring linear history means every pull request is rebased or squashed, so commits are rewritten, contributor signatures are replaced or lost, and force-pushes become routine. Merge commits keep contributors' commits as written and their signatures intact, at the cost of a graph that needs the first-parent view to read cleanly.Require linearMerge commitscontributor commitsrewrittenkept as writtencontributor signatureslost or re-signedpreservedforce-pushesroutinerarereadable by defaultyeswith --first-parentthe costs fall on contributors and auditors; the benefits on log readers
# Signature impact: how many commits on main were signed by their authors?
git log --since=90.days --format='%G? %ae %ce' main | awk '$2!=$3 {rewritten++} {n++} END {print rewritten" of "n" commits committed by someone other than the author"}'

With rebase or squash merging done by the forge, commits are created by the forge and signed with its key, so contributor signatures no longer appear on main at all; the implications are in keeping signatures valid through rebase and squash.

Step 3 — Look at collaboration effects Jump to heading

Linear history pushes every branch towards a rebase before merging. On a branch one person owns, that is easy. On a branch two people share, or one that others have built on, every rebase forces collaborators to reset, and stacked branches must be moved each time the base is rewritten.

# How often do branches with more than one author exist in your repository?
for b in $(git for-each-ref --format='%(refname:short)' refs/remotes/origin/ | grep -v HEAD); do
  n=$(git log --format=%ae "origin/main..$b" 2>/dev/null | sort -u | wc -l)
  [ "$n" -gt 1 ] && echo "$n authors: $b"
done | sort -rn | head

If shared branches are common, the linear rule costs more; the techniques that soften it are in sharing a feature branch between developers.

Step 4 — Consider what is lost from history Jump to heading

A merge commit records that a set of commits arrived together, when, through which pull request. Squash merging keeps “together” but loses the individual commits; rebase merging keeps the commits but loses the grouping. For audits and forensic work, those can matter.

# With merge commits: which commits arrived in PR #851, and when did it merge?
git log --oneline e91a2c0^1..e91a2c0^2
git log -1 --format='%ci' e91a2c0

Step 5 — Choose, and choose consistently Jump to heading

Weigh the costs against your team’s situation. Some patterns help:

Should main require linear history?If pull requests are small and single-author and nobody audits contributor signatures, linear history via squash merging is cheap and readable. If contributor signatures or per-commit history matter, keep merge commits and read with first-parent. If branches are often shared or stacked, avoid the linear rule, which makes collaboration costly.What matters most for this repository?small, single-author PRsLinear via squashcheap and tidysignatures, audit trailMerge commitsread --first-parentshared / stacked branchesNo linear ruleavoid constant rewriteswhatever you choose, use one merge method per repository

Mixing methods in one repository — some pull requests squashed, some merged, some rebased — gives the costs of all and the benefits of none. Pick one per repository and set it as the only allowed method.

gh api -X PATCH "repos/$OWNER/$REPO" -F allow_merge_commit=true -F allow_squash_merge=false -F allow_rebase_merge=false

Step 6 — Revisit the decision with data Jump to heading

After a quarter, check whether the choice delivered: are logs read? Are bisects faster? Have signature or collaboration problems appeared? A policy that was right for a small team may not suit it after it doubles.

Validation checklist Jump to heading

Frequently Asked Questions Jump to heading

Does requiring linear history prevent merge conflicts? Jump to heading

No. Conflicts happen whenever two changes touch the same lines; the merge method only changes where they are resolved — during a rebase instead of a merge.

Can linear history and signed commits coexist? Jump to heading

Yes, if authors rebase and squash locally with signing on and the forge fast-forwards. Forge-side rebase or squash replaces the author’s signature with the forge’s.

Is “rebase and merge” the same as linear history? Jump to heading

It produces linear history, but each pull request’s commits are replayed by the forge with new hashes and the forge as committer, which differs from what the author pushed.