Skip to content

Commit 898c2dc

Browse files
committed
stack map and merge behavior clarification
1 parent 38aba1b commit 898c2dc

6 files changed

Lines changed: 58 additions & 24 deletions

File tree

docs/src/content/docs/faq.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ GitHub Actions workflows trigger as if each PR in the stack is targeting the bas
7575

7676
### How do I access stack metadata in my GitHub Actions workflow?
7777

78-
For advanced use cases, you can access the stack's base ref and base SHA in workflow expressions via `github.event.pull_request.stack`. This property is only present when the PR belongs to a stack.
78+
For advanced use cases, you can access the stack's metadata in workflow expressions via `github.event.pull_request.stack`. This property is only present when the PR belongs to a stack.
7979

8080
```yaml
8181
jobs:
@@ -89,16 +89,32 @@ jobs:
8989
run: |
9090
echo "Stack base ref: ${{ github.event.pull_request.stack.base.ref }}"
9191
echo "Stack base SHA: ${{ github.event.pull_request.stack.base.sha }}"
92+
echo "PR ${{ github.event.pull_request.stack.position }} of ${{ github.event.pull_request.stack.size }} in the stack"
9293
9394
- name: Run a step only when the stack targets a release branch
9495
if: github.event.pull_request.stack != null && startsWith(github.event.pull_request.stack.base.ref, 'release/')
9596
run: echo "This stack targets a release branch"
97+
98+
- name: Run a step only on the bottom PR of the stack
99+
if: github.event.pull_request.stack.position == 1
100+
run: echo "This is the bottom PR"
101+
102+
- name: Run a step only on the lowest unmerged PR of the stack
103+
if: github.event.pull_request.stack.base.ref == github.event.pull_request.base.ref
104+
run: echo "This is the bottom PR"
105+
106+
- name: Run a step only on the top PR of the stack
107+
if: github.event.pull_request.stack.position == github.event.pull_request.stack.size
108+
run: echo "This is the top PR"
96109
```
97110
98111
| Expression | Description |
99112
|------------|-------------|
113+
| `github.event.pull_request.stack.number` | The stack's number, scoped to the repository. |
114+
| `github.event.pull_request.stack.size` | Total number of pull requests in the stack. |
115+
| `github.event.pull_request.stack.position` | 1-based position of this PR within the stack (`1` is the bottom). |
100116
| `github.event.pull_request.stack.base.ref` | The branch the entire stack ultimately targets (e.g., `main`). |
101-
| `github.event.pull_request.stack.base.sha` | The HEAD SHA of that target branch at the time of the event. |
117+
| `github.event.pull_request.stack.base.sha` | The HEAD SHA of the stack's base branch. |
102118

103119
See the [Webhooks reference](/gh-stack/reference/webhooks/) for the full details on the `stack` object in webhook payloads.
104120

docs/src/content/docs/guides/stacked-prs.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,17 @@ Each PR in a stack shows only the diff for its layer — the changes between its
2121
- **Review individual PRs** when you're focusing on a specific concern (e.g., reviewing only the API layer).
2222
- **Use the stack map** to navigate between PRs without going back to the PR list.
2323

24-
## Merging from the Bottom Up
24+
## Merging a Stack
2525

26-
Stacks are merged **from the bottom up** — you can merge any number of PRs at once, as long as they form a contiguous group starting from the lowest unmerged PR. For example, in a stack of four PRs, you can merge just the bottom one, or the bottom three together, but you cannot merge only the second and third PRs while leaving the first unmerged. Mid-stack merges are not allowed.
26+
Merging is driven by a single action: **click Merge on the highest PR you want to land, and that PR plus every unmerged PR below it merges in one atomic operation.** You do not need to merge PRs one at a time, unless you choose to.
2727

28-
1. When the lowest unmerged PR (and any PRs above it that you want to include) meet all merge requirements, merge them.
29-
2. After the merge, the remaining stack is **automatically rebased** — the next unmerged PR's base is updated to target `main` directly.
30-
3. The next unmerged PR is now at the bottom and can be reviewed, approved, and merged.
31-
4. Repeat until the entire stack is landed.
28+
- **To land the whole stack**, merge the **top** PR — every PR below it lands with it in a single step.
29+
- **To land part of the stack**, merge a lower PR — the PRs below it come along, and the PRs above stay open.
30+
- **To land a single PR**, merge the **bottom** PR - only that PR will be merged, and the rest of the PRs stay open.
31+
32+
You can merge any contiguous group, as long as it starts from the lowest unmerged PR. In a stack of four PRs you can land just the bottom one, or the bottom three together, but you can't merge only the second and third while leaving the first unmerged — a PR always brings the unmerged PRs below it along. Merging a stacked PR always merges all the unmerged PRs below it as well.
33+
34+
When you land only part of a stack, the remaining PRs are **automatically rebased** and retargeted so the next unmerged PR targets your base branch directly and is immediately ready to review and merge.
3235

3336
Once the entire stack has landed, it is complete and can't be extended. If you add new branches on top and run `gh stack submit`, the CLI automatically starts a **new** stack rooted at the trunk for those branches (a new PR on a fully merged stack would target the trunk directly rather than chaining onto the merged PRs).
3437

docs/src/content/docs/guides/ui.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@ This guide walks through the key UI components and workflows for working with St
77

88
## Navigating Stacked PRs
99

10-
When a pull request is part of a stack, a **stack navigator** appears in the PR header. This component gives you an at-a-glance view of the entire stack and lets you jump between PRs.
10+
When a pull request is part of a stack, a **stack map** appears in the PR header. This component gives you an at-a-glance view of the entire stack and lets you jump between PRs.
1111

12-
The stack navigator shows:
12+
The stack map shows:
1313

1414
- All PRs in the stack, listed in order from top to bottom
1515
- Which PR you're currently viewing (highlighted)
1616
- Clickable links to navigate directly to any PR in the stack
1717
- Link to Add to Stack, where you can create a new PR that targets the head of the topmost PR
1818
- Unstack option to dissolve the association between PRs, turning them back into standard PRs
1919

20-
![The stack navigator in a PR header](../../../assets/screenshots/stack-navigator.png)
20+
![The stack map in a PR header](../../../assets/screenshots/stack-navigator.png)
2121

2222
## Creating a Stack from the UI
2323

@@ -37,9 +37,9 @@ When you create the next PR, set its base branch to the first PR's branch. You'l
3737

3838
### Step 3: Confirm the stack
3939

40-
After creating the PR, you'll see the stack navigator appear in the header, showing both PRs linked together.
40+
After creating the PR, you'll see the stack map appear in the header, showing both PRs linked together.
4141

42-
![The stack navigator showing the newly created stack](../../../assets/screenshots/newly-created-stack.png)
42+
![The stack map showing the newly created stack](../../../assets/screenshots/newly-created-stack.png)
4343

4444
Repeat this process for each additional PR in the stack — each one targets the branch of the PR before it.
4545

@@ -101,4 +101,4 @@ To dissolve the stack entirely (turning all Stacked PRs back into independent PR
101101

102102
![Dissolving an entire stack](../../../assets/screenshots/unstack-entire-stack.png)
103103

104-
After unstacking, each PR retains its current base branch but is no longer linked to the other PRs. The stack navigator and stack-related merge requirements disappear from all affected PRs.
104+
After unstacking, each PR retains its current base branch but is no longer linked to the other PRs. The stack map and stack-related merge requirements disappear from all affected PRs.

docs/src/content/docs/index.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,14 @@ A **stack** is a series of pull requests in the same repository where each PR ta
4848
GitHub understands stacks end-to-end: the pull request UI shows a **stack map** so reviewers can navigate between layers, branch protection rules are enforced against the **final target branch** (not just the direct base), and CI runs for every PR in the stack as if they were targeting the final branch.
4949

5050
<div style="max-width: 600px; margin: 1.5rem auto;">
51-
<Image src={stackNavigator} alt="The stack navigator in a pull request header" />
51+
<Image src={stackNavigator} alt="The stack map in a pull request header" />
5252
</div>
5353

5454
## Working with Stacks
5555

56-
**While the `gh stack` CLI makes the local workflow seamless, it is entirely optional.** You can create and manage Stacked PRs directly via the GitHub UI, the API, or your standard Git workflow. If you choose to use the CLI, it handles creating branches, managing rebases, pushing to GitHub, and creating PRs with the correct base branches. On GitHub, the PR UI gives reviewers the context they need — a stack map for navigation, focused diffs for each layer, and proper rules enforcement.
56+
**While the `gh stack` CLI makes the local workflow seamless, it is entirely optional.** You can create and manage Stacked PRs directly via the GitHub UI, the API, or your standard Git workflow. If you choose to use the CLI, it handles creating branches, managing rebases, pushing to GitHub, and creating PRs with the correct base branches. On GitHub, the PR UI gives reviewers the context they need — a stack map, focused diffs for each layer, and proper rules enforcement.
5757

58-
When you're ready to merge, you can merge all or a part of the stack. Each PR can be merged directly or through the merge queue. **If you want to merge multiple PRs at once (e.g., the bottom two PRs in a stack), simply wait for CI to pass on those specific layers, and you can merge them in a single step.** After a merge, the remaining PRs in the stack are automatically rebased so the lowest unmerged PR targets the updated base branch.
58+
When you're ready to merge, click **Merge** on the highest PR you want to land — that PR **and every unmerged PR below it merge together in a single, atomic operation**. Merge the top PR to land the whole stack in one click, or merge a lower PR to land just part of it (the PRs above stay open). After a partial merge, the remaining PRs are automatically rebased so the lowest unmerged PR targets the updated base branch.
5959

6060
## Get Started
6161

docs/src/content/docs/introduction/overview.md

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ GitHub supports Stacked PRs natively, combining a rich pull request UI with the
4040

4141
When a pull request is part of a stack, a **stack map** appears at the top of the PR page. It shows every PR in the stack, their status, and lets you navigate to any layer with one click. This gives reviewers immediate context about where a PR fits in the bigger picture.
4242

43-
![The stack navigator in a pull request header](../../../assets/screenshots/stack-navigator.png)
43+
![The stack map in a pull request header](../../../assets/screenshots/stack-navigator.png)
4444

4545
### Rules and CI Enforcement
4646

@@ -55,12 +55,19 @@ This ensures that every layer of the stack meets the same quality bar before it
5555

5656
### Merging Stacks
5757

58-
The entire stack does not need to be merged at once, but PRs must be merged **from the bottom up**. GitHub supports two merge methods:
58+
You can merge your entire stack, a single PR, or a portion of the stack spanning multiple PRs. When you click **Merge** on any PR, that PR **and every unmerged PR below it land together in a single atomic operation**. So you can:
5959

60-
- **Direct merge** — Merges a PR (and all non-merged PRs below it) in a single operation, as long as all conditions are met.
60+
- **Land the entire stack in one click** by merging the top PR — every PR below it comes with it.
61+
- **Land part of the stack** by merging a mid-stack PR — the PRs below it come along, and the PRs above stay open.
62+
63+
You can't merge a PR while leaving an unmerged PR below it behind. Merging a stacked PR always merges all the unmerged PRs below it as well.
64+
65+
GitHub supports two merge methods:
66+
67+
- **Direct merge** — Merges the selected PR and all unmerged PRs below it in a single operation, as long as all conditions are met.
6168
- **Merge queue** — Works as usual but is stack-aware. For example, if the bottom PR is removed from the queue, all other PRs in the stack are also removed.
6269

63-
The resulting commit history is the same as merging each PR individually, starting from the bottom.
70+
The resulting commit history is the same as if each PR had been merged individually, starting from the bottom.
6471

6572
### Merge Methods
6673

docs/src/content/docs/reference/webhooks.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ description: Reference for the stack object in pull_request webhook event payloa
55

66
When a pull request belongs to a stack, GitHub adds a `stack` property to the `pull_request` object in webhook event payloads. This lets apps and integrations inspect the stack's ultimate target branch — not just the direct parent branch of the PR.
77

8-
The `stack` object is included in the `pull_request` webhook payload for all [pull request lifecycle events](https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#pull_request).
8+
The `stack` object is included in the `pull_request` webhook payload for all [pull request lifecycle events](https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#pull_request) whenever the pull request is part of a stack.
99

1010

1111

1212
## The `stack` Object
1313

14-
The `stack` object is nested inside the `pull_request` object and contains information about the stack's base branch:
14+
The `stack` object is nested inside the `pull_request` object. It identifies the stack, describes this PR's place within it, and reports the stack's base branch and ultimate merge target:
1515

1616
```json
1717
{
@@ -24,6 +24,10 @@ The `stack` object is nested inside the `pull_request` object and contains infor
2424
"sha": "abc123..."
2525
},
2626
"stack": {
27+
"id": 123456,
28+
"number": 50,
29+
"size": 5,
30+
"position": 2,
2731
"base": {
2832
"ref": "main",
2933
"sha": "def456..."
@@ -37,8 +41,12 @@ The `stack` object is nested inside the `pull_request` object and contains infor
3741

3842
| Field | Type | Description |
3943
|-------|------|-------------|
44+
| `pull_request.stack.id` | `integer` | Global identifier for the stack. |
45+
| `pull_request.stack.number` | `integer` | The stack's number, scoped to the repository. |
46+
| `pull_request.stack.size` | `integer` | Total number of pull requests in the stack. |
47+
| `pull_request.stack.position` | `integer` | 1-based position of this PR within the stack, where `1` is the bottom (the PR closest to the stack's base). |
4048
| `pull_request.stack.base.ref` | `string` | The branch the entire stack ultimately targets (e.g., `main`). |
41-
| `pull_request.stack.base.sha` | `string` | The HEAD SHA of that target branch at the time of the event. |
49+
| `pull_request.stack.base.sha` | `string` | The HEAD SHA of the stack's base branch. |
4250

4351
`pull_request.base.ref` is the direct parent branch of an individual PR (the branch below it in the stack), while `pull_request.stack.base.ref` is the ultimate target of the entire stack. These differ for all PRs in the stack except the bottom one.
4452

0 commit comments

Comments
 (0)