Collaboration

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:

sh
1cafe stack link 12 13 14
2cafe stack list
3cafe 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:

sh
1cafe stack submit --name my-change --base main --vcs git --dry-run
2cafe 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:

sh
1cafe stack merge 14 --dry-run
2cafe 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:

sh
1cafe 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:

sh
1cafe 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:

sh
1cafe stack close --stack 7 --dry-run
2cafe 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.

Read as MarkdownGitCafe documentation
Documentation