You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Browse filesBrowse the repository at this point in the historyBrowse files
Test
committed
fix(stacks): resolve GitHub stack membership by checkout identity, not branch name
The Stacks view matched a stack purely by `git branch --show-current`, so
switching to a PR (review worktree, detached HEAD, `gh pr checkout`/rename)
never resolved a stack even though the checkout was clearly a member. Detect
via a precedence-ordered identity match instead: PR number (parsed from a
`pr/<n>-review` branch) > branch name > upstream ref > HEAD commit sha,
falling back to a target-only match, with dissolved (`open: false`) stacks
excluded. Also derive per-member status (open/draft/merged/closed) and a
local "Blocked downstack" approximation, since the Stacks API doesn't report
per-PR mergeability, and fix a stale-view race and a leaked debounce timer
in the refresh path.
Restyle the Stacks webview rows to match GitHub's own stack map: a status
icon + badge per PR, dimmed merged/closed rows, and the target rendered as a
code chip.
Copy file name to clipboardExpand all lines: README.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -41,7 +41,7 @@ All commands are grouped under the `GSC:` prefix in the Command Palette.
41
41
| Open a terminal in a selected worktree's directory |`GSC: Open Worktree Dev Terminal...`|[Open worktree dev terminal](docs/open-worktree-dev-terminal.md)|
42
42
| Remove several Git worktrees at once with a single confirmation |`GSC: Remove Multiple Worktrees...`|[Remove multiple worktrees](docs/remove-multiple-worktrees.md)|
43
43
| Browse all worktrees for the open repositories in a dedicated "Worktrees" view (activity bar), with dirty/ahead-behind/PR-review status, last commit + relative age, an upstream-gone flag with a dedicated inline Remove action, an auto-stash marker, live refresh on external git activity, and a badge showing the count of dirty worktrees, plus inline Open/Terminal/Copy WIP/Remove actions |*(tree view — right-click an item for Add to Workspace, Copy Path, Reveal in Finder/Explorer)*| — |
44
-
| Detect the GitHub-native [stacked PR](https://docs.github.com/en/rest/pulls/stacks) chain the current branch belongs to, and browse it in a dedicated "Stacks" view (activity bar) showing each PR's title and branch plus the branch the stack is ultimately targeting. Click a row (or its target chip) to check it out using the currently selected checkout/stash strategy; right-click for "Open PR in Browser". Nothing is cached — an in-view refresh icon re-checks live at any time. A status bar indicator (`$(layers) <position>/<size>`) appears only while the current branch is part of a stack; click it to reveal the Stacks view. |`GSC: Refresh Stacks`|[Stacks](docs/stacks.md)|
44
+
| Detect the GitHub-native [stacked PR](https://docs.github.com/en/rest/pulls/stacks) chain the current checkout belongs to — resolved by branch, PR-review worktree, HEAD commit, or upstream ref, so it works whether you switched branches or switched PRs — and browse it in a dedicated "Stacks" view (activity bar) with a GitHub-style status icon/badge per PR (open/draft/merged/closed/blocked downstack) plus the branch the stack is ultimately targeting. Click a row (or its target chip) to check it out using the currently selected checkout/stash strategy; right-click for "Open PR in Browser". Nothing is cached — an in-view refresh icon re-checks live at any time. A status bar indicator (`$(layers) <position>/<size>`) appears only while the current checkout is part of a stack, including on a matched detached HEAD; click it to reveal the Stacks view. |`GSC: Refresh Stacks`|[Stacks](docs/stacks.md)|
45
45
| Create a new PR from selected commits in another GitHub PR |`GSC: Clone Pull Request...`|[GitHub PR clone](docs/github-pr-clone.md)|
46
46
| Generate and optionally push a tag from a reusable template |`GSC: Create Tag from Template...`|[Create tag from template](docs/create-tag-from-template.md)|
47
47
| Create and check out a branch from a template (Jira, file, regex, scripts) |`GSC: Create Branch from Template...`|[Create branch from template](docs/create-branch-from-template.md)|
Copy file name to clipboardExpand all lines: docs/stacks.md
+14-6Lines changed: 14 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -18,21 +18,29 @@ Whether a single PR onto trunk counts as a stack, how forks in history are resol
18
18
19
19
## The Stacks View
20
20
21
-
Shows the stack containing the **current branch**, top PR first, target branch as a chip at the bottom. Each row shows the PR titleand `#number · branch`; the current branch/target is highlighted.
21
+
Shows the stack containing the **current checkout**, top PR first, target branch as a code chip at the bottom. Each row shows a GitHub-style status icon, the PR title, a right-aligned status badge, and `#number · head-ref` (the PR's own head branch — not necessarily your local branch name, see [Detection](#detection)); the current row is marked with a left accent bar.
22
22
23
-
-**Click a row (or the target chip)** to check out that branch, using whichever [stash mode](switch-mode.md) is currently active — including the manual prompt if that's what's configured.
23
+
-**Status icon and badge**: open (green), draft (dashed, "Draft"), merged (purple check, "Merged"), closed (red ×, "Closed"), or blocked (warning circle, "Blocked downstack" — shown when an unmerged draft/closed PR sits below it in the stack; this is a local approximation, since the Stacks API doesn't report per-member mergeability). Merged and closed rows render dimmed but stay in the list, matching their place in the real stack.
24
+
-**Click a row (or the target chip)** to check out that PR's head branch, using whichever [stash mode](switch-mode.md) is currently active — including the manual prompt if that's what's configured.
24
25
-**Right-click a row** (or use the inline external-link icon) for "Open PR in Browser".
25
26
- The target chip shows **⇡N ⇣N** (commits waiting to be pushed / commits to pull), read directly from the branch's upstream tracking info — the same convention as the Worktrees view — whenever the target branch has an upstream configured. Next to it, a **fetch icon (⟳, "Fetch latest changes")** fetches the target branch from its remote (updating the remote-tracking ref only, no checkout, no merge) and refreshes the indicator.
26
-
- The **refresh icon (⟳)** in the view's title bar re-fetches the current branch's stack status from GitHub on demand — useful right after a stack changes on GitHub (a PR merged, or the stack was reordered/dissolved), since nothing is cached locally.
27
-
- When the current branch isn't part of any stack, the view shows an empty state with a Refresh button.
27
+
- The **refresh icon (⟳)** in the view's title bar re-fetches the current stack status from GitHub on demand — useful right after a stack changes on GitHub (a PR merged, or the stack was reordered/dissolved), since nothing is cached locally.
28
+
- When the current checkout isn't part of any stack, the view shows an empty state with a Refresh button.
28
29
29
30
## Status Bar Indicator
30
31
31
-
`$(layers) <position>/<size>` appears immediately to the left of the stash-mode item, but **only** while the current branch is part of a detected stack — it's hidden when stacks are disabled, the extension's status bar is off, HEAD is detached, or the branch simply isn't stacked. The count is of **stacked PRs only** — the target branch doesn't count toward `<size>`, so sitting on the target itself shows no position (there's no PR there). Its tooltip lists the chain top-to-bottom with PR numbers/titles, plus the target branch on its own line. Click it to reveal the Stacks view.
32
+
`$(layers) <position>/<size>` appears immediately to the left of the stash-mode item, but **only** while the current checkout is part of a detected stack — it's hidden when stacks are disabled, the extension's status bar is off, or the checkout simply isn't stacked. Unlike earlier versions, a detached HEAD does **not** hide the indicator on its own: a detached checkout sitting on a stack member's commit is still resolved and shown (see [Detection](#detection)). The count is of **stacked PRs only** — the target branch doesn't count toward `<size>`, so sitting on the target itself shows no position (there's no PR there). Its tooltip lists the chain top-to-bottom with PR numbers/titles, plus the target branch on its own line. Click it to reveal the Stacks view.
32
33
33
34
## Detection
34
35
35
-
Detection is automatic and always on for GitHub repositories, with no configuration knob: whenever the current branch is the target or a stacked PR's head in one of the repository's stacks (as reported live by `GET /repos/{owner}/{repo}/stacks`), it shows up. Nothing is cached — a stack can be reordered or dissolved on GitHub at any time, so every refresh re-fetches live rather than risking a stale view.
36
+
Detection is automatic and always on for GitHub repositories, with no configuration knob. Every refresh resolves the current checkout's *identity* — its branch name, HEAD commit sha, any `pr/<n>-review` worktree it's parsed from, and its upstream branch name — and matches that identity against the members and targets of the repository's stacks (as reported live by `GET /repos/{owner}/{repo}/stacks`), by precedence:
37
+
38
+
1.**PR number** — a `GSC: Review PR by number` / "Review PR in worktree" checkout (branch `pr/<n>-review`) matches PR `<n>` directly, even though that branch name never appears in any PR's `head.ref`.
39
+
2.**Branch name** — the checked-out local branch equals a stacked PR's `head.ref`, or the stack's `base.ref` (a target-only match, used only when no member matched).
40
+
3.**Upstream ref** — the checked-out branch's remote-tracking branch (e.g. after `gh pr checkout` or a local rename) equals a stacked PR's `head.ref`.
41
+
4.**HEAD commit sha** — a detached HEAD sitting exactly on a stacked PR's `head.sha`.
42
+
43
+
A member match always wins over a target match, even across different stacks (e.g. standing on `main`, which is the target of one stack but also happens to be a stacked PR's head in another, resolves to the stack you're actually in). Stacks with `open: false` (dissolved on GitHub) are never matched. Nothing is cached — a stack can be reordered or dissolved on GitHub at any time, so every refresh re-fetches live rather than risking a stale view.
0 commit comments