From Overview / What Is a Stack?:
A pull request stack consists of two or more pull requests in the same repository where:
- The first (bottom) pull request targets the main branch (e.g., main).
- Each subsequent pull request targets the branch of the PR below it.
┌── feat/frontend → PR #3 (base: feat/api-endpoints) ← top
┌── feat/api-endpoints → PR #2 (base: feat/auth-layer)
┌── feat/auth-layer → PR #1 (base: main) ← bottom
main (trunk)
[endquote]
Merging to the base branch is fundamentally wrong for this. In your example here, api-endpoints is not logically part of auth-layer, so should not merge to it. You should separate "base" and "target" (e.g. main, super-feature, etc). Normally all branches in a stack will merge to the same target.
You already track "target" as distinct from base - your own Overview states each PR is evaluated for rules and protections using "its final target branch (e.g., main), not the branch it directly targets." So the concept exists; it's just confined to rule evaluation and discarded everywhere else. Promote it to a first-class merge destination.
Result should be something like:
$ git log --all --graph --decorate --pretty=oneline --abbrev-commit
* 043bf03 (HEAD -> main) Merge pull request #2 from username/feat/2
|\
| * 88624f8 (feat/2) Feature 2
* | 39f3460 Merge pull request #1 from username/feat/1
|\|
| * 0f1e961 (feat/1) Feature 1
|/
* 04a9dac Initial commit
Related, I made the same point to Git Butler, but they're constrained by the existing GitHub implementation. But you are GitHub, now deciding the next implementation - not constrained.
Along with this, the implementation should display and enforce "below" branches in the stack as prerequisites. feat/2 should be blocked from merging until feat/1 has merged. You'll have to make this explicit, instead of just a side effect of merging to the base branches.
From Overview / What Is a Stack?:
[endquote]
Merging to the base branch is fundamentally wrong for this. In your example here,
api-endpointsis not logically part ofauth-layer, so should not merge to it. You should separate "base" and "target" (e.g.main,super-feature, etc). Normally all branches in a stack will merge to the same target.You already track "target" as distinct from base - your own Overview states each PR is evaluated for rules and protections using "its final target branch (e.g.,
main), not the branch it directly targets." So the concept exists; it's just confined to rule evaluation and discarded everywhere else. Promote it to a first-class merge destination.Result should be something like:
Related, I made the same point to Git Butler, but they're constrained by the existing GitHub implementation. But you are GitHub, now deciding the next implementation - not constrained.
Along with this, the implementation should display and enforce "below" branches in the stack as prerequisites.
feat/2should be blocked from merging untilfeat/1has merged. You'll have to make this explicit, instead of just a side effect of merging to the base branches.