docs(pull-request-workflow): two preconditions a stack has to meet - #229
Conversation
The stacked-PR material covers merge order, retargeting and lost approvals - everything that happens once the stack exists. Two things that decide whether it can exist at all were missing. A pull request's base must be a branch in the repository it targets. Contributing from a fork, the base branch lives in the fork, so `gh pr create --base` answers "Base ref must be a branch" and there is no stack to be had. One API call on .permissions.push settles it before the branch is built. And a split is only real if both halves stand on their own. A test and the CI change that lets it pass read like two things and are one; where a diagnosed CI failure has one half causing it and the other fixing it, the question is already answered and the split cannot be delivered. Both were paid for on the same day: a split proposed for phpDocumentor/guides#1345, built as a branch and a PR, then reversed - the halves were inseparable, and the follow-up could not have been stacked upstream anyway. Assisted-by: claude-code:claude-opus-5 Agent-Session: https://claude.ai/code/session_014H1xwaAmrQRWUA3vx8bJcD Agent-Host: 0493f0 Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
… clause The note quoted `Base ref must be a branch` alone. GitHub answers with four clauses, and a reader matching their own output against one of them will not recognise it. One of the others actively misleads: `No commits between …` is false in the sense it suggests - the branches do differ - and checking that is exactly the detour this note exists to prevent. Quote all four and name which one is the cause. Assisted-by: claude-code:claude-opus-5 Agent-Session: https://claude.ai/code/session_014H1xwaAmrQRWUA3vx8bJcD Agent-Host: 0493f0 Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
|
|
Copilot answered the ruleset's request on It caught one thing. The note quoted Verified on the head: The Self-review: e7528d5 Assisted by claude-code:claude-opus-5 — Session |



Problem
The stacked-PR material covers what happens once a stack exists: merge order, retargeting,
--delete-branchclosing the child, approvals lost when the base merges. Two things that decide whether the stack can exist at all were not written down, and both were paid for in one afternoon.A base must be a branch in the target repository. Contributing from a fork, the feature branch lives in the fork, so upstream has nothing to point at:
The check is one call —
gh api "repos/$UPSTREAM" --jq '.permissions.push'— and it belongs before the branch is built, not after the PR is refused.A split is only real if both halves stand on their own. A test and the CI change that lets it pass read like two things and are one. Worse, the coupling is usually already proven at the moment the split is proposed: if you diagnosed a CI failure where one half causes it and the other fixes it, you have your answer and the split is a promise you cannot keep.
Change
Two sections ahead of the existing stacked-PR material, since both are preconditions for it:
Observed
phpDocumentor/guides#1345, 2026-08-25. A review round grew the PR past its subject, so the extra work was split onto its own branch and committed — then the upstream PR could not be opened (
push: falseon the base repo), and the halves turned out to be inseparable anyway: any test loading the class hits the CI failure the other half fixes, in every suite. Branch, PR and description were rebuilt around the split and then rebuilt again to undo it.Assisted by claude-code:claude-opus-5 — Session