Stacked pull requests
A stack is an ordered set of open pull requests in one repository. Each pull
request targets the previous one's source branch; the bottom pull request targets
the landing base, such as main. Use a stack when a change depends on another
change that has not yet merged.
You need repository read access to view a stack and write access to change it.
A pull request can belong to only one active stack and cannot be closed on its
own while it remains in that stack: close the stack instead (see
Closing a stack). Closing a member alone returns
PULL_REQUEST_IN_ACTIVE_STACK and names the stack.
View or create a stack
Open /<owner>/<repo>/stacks for the list, or
/<owner>/<repo>/stacks/<stackNumber> for one stack. A member pull request also
shows its stack in the sidebar.
From a local repository with the Cafe CLI signed in, you can link existing pull requests in bottom-to-top order:
| 1 | cafe stack link 12 13 14 |
| 2 | cafe stack list |
| 3 | cafe stack status 14 |
Replace the example numbers with your own. A stack holds 1 to 50 open pull requests forming a linear chain: pull 13 must target pull 12's branch, and pull 14 must target pull 13's branch. Linking does not publish local commits.
To publish local commits and later extend the same stack, reuse its submission name and base:
| 1 | cafe stack submit --name my-change --base main --vcs git --dry-run |
| 2 | cafe stack submit --name my-change --base main --vcs git |
The existing members must be an exact prefix of the planned stack. New members are appended in order with revision checks; a changed or divergent stack stops submission. If a reply is lost, the CLI inspects the exact stack before continuing. Submission is not atomic: published branches and created pull requests remain after a later failure. Inspect them and rerun with the same name to resume; do not create a replacement stack to bypass a conflict.
An active GitHub App mirror with pull-request synchronization can import GitHub stacks and synchronize local creation, appending and unstacking. Changes reach GitHub asynchronously; check synchronization status before assuming both sides agree. GitHub stacks need two pull requests, so a one-member stack stays a plain pull request on GitHub until a second member is appended. Merging or closing that pull request on GitHub dissolves the one-member stack.
Landing
Landing merges from the bottom through a selected member. As members merge, they leave the active stack and the next member targets the landing base. The stack is completed after its last member lands; its completed results remain readable.
Open pull requests outside the stack that target a landed member's branch also
move to the landing base when that member lands. A pull request still targeting
a landed member's branch (for example, one opened after the landing) cannot be
merged there; retarget it first with cafe pr edit <number> --base <landing base>.
A stack member can only merge through its stack: cafe pr merge on a member
reports its stack and refers you to cafe stack merge.
Native repositories
For a repository hosted directly in GitCafe, use the CLI from its local checkout:
| 1 | cafe stack merge 14 --dry-run |
| 2 | cafe stack merge 14 --strategy merge --yes |
The preview shows recorded readiness; permissions, branch state and merge
requirements are checked again when the merge runs. Replace 14 with the last
pull request you intend to land. --stack <number> instead selects the whole stack.
Only the merge strategy can land multiple members in one request. Rebase
can land a single member; a multiple-member request returns
STACK_STRATEGY_REQUIRES_RESTACK. Native stack landing does not support
squash and returns STACK_STRATEGY_UNSUPPORTED.
Agent tokens delegated from your account can land a stack with the same repository write and merge access a personal token needs.
One merge approval covers the selected prefix. Landing continues after the request returns and after asynchronous native merges settle. It rechecks access and merge requirements for each member, and stops if an approved source head or the landing base changes. It never silently adds commits to the approved scope.
If the result is pending or you lose the response, inspect the existing operation:
| 1 | cafe stack merge --stack 7 --operation latest |
Replace 7 with your stack number. Older operations without retained authorization
can require fresh authorization (awaiting_credential). Use the explicit operation
ID to resume after the pending member settles:
| 1 | cafe stack merge --stack 7 --operation <operation-id> --resume --yes |
Resume with the same account and delegation that started it. Do not start a new merge to recover a pending one. The browser also recovers the relevant unfinished landing when you reload its pull request. If fresh authorization is required, it offers Resume landing only after any admitted child merge has settled. Resume continues the original operation and scope using the stack's current revision; it does not create a replacement operation. If a child is still reconciling, the page keeps checking it and offers Resume landing when it settles. A reloaded native operation that stopped before admitting its next child can also be resumed with the same operation ID after its coordinator lease expires. If the coordinator is still active, Resume leaves it in control.
GitHub mirrors
GitHub stack landing requires an active App mirror with pull-request sync and
GitCafe writeback enabled. GitHub performs the merge and supports merge, squash and rebase. Check its operation until GitHub confirms the outcome. The CLI can read
the latest result with --operation latest, but its explicit operation-ID option
and --resume support native operations only. If a GitHub operation needs attention, check its status before attempting another merge.
A one-member stack that was never mirrored as a GitHub stack cannot land this
way; append a member, or unstack it and merge the pull request.
Closing a stack
Closing dissolves the stack and closes each of its open pull requests without merging them, for example after their changes landed some other way:
| 1 | cafe stack close --stack 7 --dry-run |
| 2 | cafe stack close --stack 7 --yes |
Replace 7 with your stack number, or pass a member pull request number instead
of --stack. Members that already landed stay merged. Closing needs repository
write access and, for each open member, the access that closing that pull
request on its own needs: you wrote it, or you can triage it. Either the stack
dissolves and every open member closes, or nothing changes. A stack that is
landing or restacking cannot be closed until that operation finishes. Closed
pull requests can be reopened one by one; the stack cannot be restored.
Unstacking
Unstacking dissolves a stack without closing its pull requests. A stack cannot be arbitrarily reordered, and individual members cannot be removed.
Restack
Restacking updates dependent branches onto their current bases and rewrites their
commits. Use Restack in a member's sidebar to start at that member, or
cafe stack restack --stack <number> to start with the whole stack. It requires
restack support on the instance and repository write access.
When a lower member is rewritten, each upper member replays only its own
commits onto the rewritten one. A member that no longer contains its parent's
previous tip stops with STACK_RESTACK_STALE. On an instance whose platform does
not support this yet, the restack stops with RESTACK_UPSTREAM_REBASE_UNAVAILABLE.
Following members then report STACK_RESTACK_BLOCKED_BY_PREDECESSOR; review the
completed steps, then rebase the remaining layers locally and push them. Do not
assume a failed stack operation means none of its branches changed.
If an operation reports reconciliation_required, its outcome is uncertain.
Inspect it with cafe stack restack --stack <number> --operation latest. A caller
with repository write access can ask the API to reconcile the exact operation
with POST .../restacks/<operation>/reconcile and the stack's
expectedRevision. A committed native publication is finalized without another
rebase or branch update, but only after its durable authority projection is
ready. Missing, unavailable, malformed, incomplete, or unknown status remains
held. A native definite non-commit has no projection fields and fails and
releases the operation. A push observed after the uncertain restack is never overwritten;
that conflict remains held for manual resolution. Reading status alone does not
reconcile or repeat the restack. Legacy operations without a prepared publish
identity and failures before publication was prepared cannot yet be released
automatically.
The endpoint returns 202 while the outcome is held and 200 for a terminal
operation. Recovery may finalize the published step but mark the operation
failed because untouched successors need a fresh restack. Re-read the stack
before starting that new operation; do not assume failed means no branch moved.