Skip to content

docs: correct the stacked-PR guidance for a rebase-only repository - #159

Open
thecodedrift wants to merge 1 commit into
mainfrom
docs/rebase-only
Open

docs: correct the stacked-PR guidance for a rebase-only repository#159
thecodedrift wants to merge 1 commit into
mainfrom
docs/rebase-only

Conversation

@thecodedrift

Copy link
Copy Markdown
Member

main keeps a linear history now, so the repository allows rebase-and-merge only — squash and merge-commit are both disabled:

squash=false merge=false rebase=true

Three pieces of stacked-PR guidance were wrong under that, and two of them fail quietly.

gh pr merge --merge no longer exists as an option

The section titled "Use merge-commit, not squash, for a stack" recommended exactly the flag that now errors. Worse, the reasoning is unavailable rather than merely unfashionable: it advised merge-commits so children stay clean, and rebase gives that up by construction. Rebase replays a branch onto main as new commits with new SHAs, so after each merge every child contains the pre-rebase versions of its ancestors — diverged history, not merely behind. Each one has to be rebased and force-pushed between merges.

That is now written as the expensive-but-only path, with the actual command sequence, rather than as a preference between options that no longer exist.

The stack-health check was unsound

# reports STRANDED for a stack that landed perfectly
git merge-base --is-ancestor origin/<tip> origin/<bottom>

It asks whether the tip's commits are ancestors of the branch that absorbed them. After a rebase merge they never are, because they were replayed under new SHAs. Replaced with a content diff, and the healthy state named explicitly — an empty diff across differing SHAs looks alarming and is exactly right.

Two behaviours measured while landing #153 and #154

  • Branch protection is strict_up_to_date: true, so the next PR reports mergeable_state: "behind" until rebased. That is the protection asking for the rebase you owe it, not a conflict.
  • rebaseable reads null for a while after each merge while GitHub recomputes. Treating that null as "not mergeable" is what stranded commits mid-stack previously, so the guidance now says to poll until it is a boolean.

Rebase-and-merge lands unsigned commits

-S is mandatory locally, but GitHub does not re-sign what it rebases — every commit on main reports N:

$ git log --format='%G? %h %s' -3 origin/main
N 9e87aa6 fix(cli): give every ast-grep rule a .tests/ so one rule can't fail them all
N 7040c9b fix(cli): decide "whole project" the same way in both static engines
N afb4831 fix(cli): let ast-grep rules see inside hidden directories

Nothing to fix, but worth knowing in both directions: on main it is expected, and a fresh commit reading N before it reaches main means the flag was missed, which is the real problem it resembles.

Docs only — no code, no changeset.

`main` keeps a linear history now, so the repository allows rebase-and-merge
only — squash and merge-commit are both disabled. Three pieces of guidance
were wrong under that, and two of them fail quietly.

"Use merge-commit, not squash, for a stack" recommended `gh pr merge --merge`,
which now errors. The advice it carried is also unavailable rather than merely
unfashionable: rebase replays a branch onto main as new commits, so every
child of a merged branch has diverged history and must be rebased and
force-pushed between merges. That is the expensive path, and there is no
cheaper one to prefer.

The stack-health check was unsound. `git merge-base --is-ancestor` asks
whether the tip's commits are ancestors of the branch that absorbed them, and
after a rebase merge they never are — it reports STRANDED for a stack that
landed perfectly. Replaced with a content diff, and the healthy state named
explicitly, because an empty diff over differing SHAs looks alarming and is
not.

Records two things measured while landing #153 and #154: branch protection is
strict, so the next PR reads `mergeable_state: "behind"` until rebased, and
`rebaseable` reads `null` for a while after each merge while GitHub recomputes
— reading that null as "not mergeable" is what stranded commits mid-stack
before.

Also records that GitHub does not re-sign what it rebases, so every commit on
main reports `N` despite `-S` being mandatory locally. Worth knowing in both
directions: on main it is expected, and before main it means the flag was
missed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Cyga14bww8rmazH2XrF8ms
Copilot AI lite review requested due to automatic review settings August 24, 2026 15:49

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants