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
{{ message }}
Repository navigation
Add git stack get to pull a pull request's stack down - #65
Reviewing someone else's stacked PRs meant creating each branch by hand and tracking them one at a time. git stack get takes a PR number, URL or branch name and brings its stack down locally.
How it works
If GitHub has the PR in a stack, gh stack checkout does the work and creates the missing branches.
If the PR is in no stack on GitHub (or the repo has no stacked PRs), get walks down the open PRs it is based on, down to the first base that has none, which becomes the trunk. It creates those branches from the remote and tracks them as a new stack, the way init does.
A target already tracked here is only brought up to date.
Existing branches are fast forwarded with sync's code. Nothing is rebased or pushed, and diverged branches are left alone with a warning.
Forks are refused, since their branches are not on our remote. A PR based on a branch already in another local stack is also refused.
Other changes
get alias, and stack_get MCP tool (with source, created, updated, behind in its result).
forge.PR port method, so a PR can be looked up by number, including forks. Fork is now set on forge.PullRequest.
forge.OpenPRFor port method, which finds a branch's open PR however old it is (the base-PR walk and branch-name targets use it, rather than the 500 most recent PRs).
A URL for another repository is refused, and a checkout that fails after branches moved is reported as partial (checkedOut: false) so undo still covers it.
Tracker.ImportStack port method, implemented by the ghstack adapter around gh stack checkout. Exit codes 2, 3 and 9 map to not-in-stack, a local ordering conflict, and stacks unavailable.
get is undoable, and the undo docs list it.
Shell completion offers open PRs from the cache (never refreshes it).
README, docs/architecture.md, docs/mcp.md, the skill and MCP instructions are updated.
Review notes
A branch that exists locally is never updated by gh stack checkout, so get fetches first and then runs sync's fast forward on the stack.
get on a lone PR records its stack the same way init does, so stack_submit can later push it.
The cmd/get_test.go, pkg/app/get_test.go, pkg/mcp/server_test.go and pkg/backend/ghstack tests cover the new paths, including undo and refusals.
Reviewing someone else's stacked PRs meant creating each branch by hand
and tracking them one at a time. get takes a PR number, URL or branch
name and brings its stack down: gh stack checkout does the work when
GitHub has the PR in a stack, and for a lone PR get walks down the open
PRs it is based on and tracks them as a new stack. Branches that already
exist are fast forwarded with sync's code, never rebased or pushed, and
forks are refused since their branches are not on our remote.
Also adds the get alias, the stack_get MCP tool, and the matching docs
and skill entries.
- Refuse a pull request URL for another repository instead of reading
its number as one of ours.
- Report a failed checkout after branches moved as a partial result, so
undo records it; the result's checkedOut says whether it happened.
- Look an untracked pull request number up on the forge and check its
branch against the graph, so getting a lone PR again finds it.
- Work out needsRestack after the fast forwards, for every source.
- Find base pull requests by branch with Forge.OpenPRFor rather than in
the 500 most recent, which also runs the lookup on the step's context.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Import failures can leave branch and metadata changes without undo, cross-worktree stack overlaps can silently drop tracking, and closed or merged PRs can incorrectly be accepted.
- When gh stack checkout fails after saving the imported stack, carry on
with the target from that stack so the failed checkout is a partial,
undoable result.
- Refuse a closed, merged or fork pull request before gh stack sees it.
- Check every branch is on the remote before creating any for a lone pull
request, and delete the ones created if tracking them fails.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Unresolved issues allow invalid imports, reject valid targets, leave stale stack boundaries, and cause partial mutations that cannot be fully rolled back or undone.
No open issues 🎉
7 previously missed issues
In code that hasn't changed since last review
Undo does not restore the original detached HEAD
pkg/app/get.go:123
Starting get from detached HEAD creates a stack that undo cannot fully restore: planWorktreeMoves skips the saved detached checkout. Undo removes the metadata but leaves the new branch checked out instead of returning to the original commit. Restore detached HEAD during undo, or reject this starting state before get mutates anything.
Sync fails when the default trunk exists only on the remote
pkg/app/get.go:145
With no tracked stacks, gatherSync requires an existing local default branch, even when origin/HEAD names a remote-only trunk. A clone containing only a feature branch therefore fails before looking up the PR, although the import could create the missing trunk. Discover the fetch remote without requiring a local trunk, then obtain the trunk from the imported stack or PR chain.
Post-import failures leave changes without undo records
pkg/app/get.go:200
Cancelling the “Checking ” step after import leaves the newly recorded stack and any completed fast-forwards in place, but this ordinary error prevents undo from recording them. Handle failures from the first mutation onward as rollback or undoable partial results, including the later getNeedsRestack failure. Populate the result before these steps so CLI and MCP callers retain what changed.
Fast-forwarding leaves child base metadata stale
pkg/app/get.go:209
If local a is at A1 while remote a and child b contain A2, initialization records b.Base = A1, and fast-forwarding a leaves that boundary stale despite reporting no restack needed. Amending A2 with modify then makes the planner replay A2 as part of b, which can cause a spurious conflict. Reconcile recorded bases with final parent tips where the child contains them, preserving boundaries for diverged branches and branches sitting exactly on their parent.
Untracked branch-name targets bypass the pre-import eligibility check. If a merged branch still exists in a GitHub stack with an open PR above it, get <branch> imports and checks it out, although getting the same PR by number is refused. Resolve the branch's open PR before importing and reject targets without one.
Failed imports leave newly created branches untracked
pkg/app/get.go:343
gh stack checkout can create branches before saving metadata: importing [a, topic/b] with an existing local topic branch creates a, then fails on the ref-name conflict. No saved stack is found here, so a remains untracked and the ordinary error leaves no undo entry. Roll back branches created by the failed import; marking it partial alone is insufficient because undo excludes untracked refs.
Fork PRs crowd out native matches before the result limit
pkg/forge/github/github.go:223
The 20-result limit is applied before forks are filtered out, so 20 newer fork PRs named patch-1 can hide an older same-repository PR with that head name. This rejects a valid branch target or ends the base-PR walk early, incorrectly treating that branch as trunk. Exclude forks server-side before limiting, or paginate until a native match is found or all results are exhausted.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Reviewing someone else's stacked PRs meant creating each branch by hand and tracking them one at a time.
git stack gettakes a PR number, URL or branch name and brings its stack down locally.How it works
gh stack checkoutdoes the work and creates the missing branches.getwalks down the open PRs it is based on, down to the first base that has none, which becomes the trunk. It creates those branches from the remote and tracks them as a new stack, the wayinitdoes.Other changes
getalias, andstack_getMCP tool (withsource,created,updated,behindin its result).forge.PRport method, so a PR can be looked up by number, including forks.Forkis now set onforge.PullRequest.forge.OpenPRForport method, which finds a branch's open PR however old it is (the base-PR walk and branch-name targets use it, rather than the 500 most recent PRs).partial(checkedOut: false) so undo still covers it.Tracker.ImportStackport method, implemented by theghstackadapter aroundgh stack checkout. Exit codes 2, 3 and 9 map to not-in-stack, a local ordering conflict, and stacks unavailable.getis undoable, and the undo docs list it.docs/architecture.md,docs/mcp.md, the skill and MCP instructions are updated.Review notes
gh stack checkout, sogetfetches first and then runs sync's fast forward on the stack.geton a lone PR records its stack the same wayinitdoes, sostack_submitcan later push it.cmd/get_test.go,pkg/app/get_test.go,pkg/mcp/server_test.goandpkg/backend/ghstacktests cover the new paths, including undo and refusals.