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
gh stack matches the current branch against .git/gh-stack by exact string
(resolveStack → FindAllStacksForBranch → Stack.Contains, cmd/utils.go:395,
internal/stack/stack.go:241). Renaming a stacked branch with git branch -m is not
observed, so the stack file keeps pointing at a name that no longer exists and every
stack command bails out with the same generic message.
gh stack modify already renames a branch in git and in the stack file together
(internal/modify/apply.go:190-228, verified: both .git/gh-stack and the git branch are
updated), so the invariant is understood. This issue is about a rename performed outside
gh-stack, which is how most people rename a branch.
Related but distinct: #137 reaches the same stranded state through sync --prune
(branch deleted, stack entry left behind), and #193 is the same family of "git operations
performed outside gh-stack aren't observed".
Reproduction
Requires an origin remote, but the repository need not exist.
gh stack init with no arguments errors with "interactive input required", so the branch
name is passed explicitly to keep the repro scriptable.
Observed
.git/gh-stack is byte-identical before and after the rename; it still records "branch": "feat/test".
Command
Output
gh stack view
✗ current branch "feat/test-1" is not part of a stack
gh stack add feat/test-2
same
gh stack unstack / unstack --local
same
gh stack checkout feat/test (old name)
✗ failed to checkout feat/test: failed to run git: error: pathspec 'feat/test' did not match any file(s) known to git
gh stack checkout feat/test-1 (new name)
✗ no locally tracked stack found for "feat/test-1"
gh stack unstack <n> --local would remove the entry, but a stack that has not been
submitted has no stack number (Number int \json:"number,omitempty"``,
internal/stack/stack.go:46), so it cannot be targeted:
$ gh stack unstack 1 --local
✗ stack #1 is not tracked locally
With no gh stack list (#150) and an interactive-only checkout picker, the ways out are
renaming the branch back (verified: this fully restores the stack) or editing .git/gh-stack by hand.
Expected
Diagnose instead of denying. Before printing "is not part of a stack"
(cmd/utils.go:234-243), check whether a recorded stack references a branch that no
longer exists. git.BranchExists is already used throughout (cmd/sync.go:413,
cmd/modify.go:315, …). checkout should also stop surfacing git's raw pathspec ... did not match error.
Summary
gh stackmatches the current branch against.git/gh-stackby exact string(
resolveStack→FindAllStacksForBranch→Stack.Contains, cmd/utils.go:395,internal/stack/stack.go:241). Renaming a stacked branch with
git branch -mis notobserved, so the stack file keeps pointing at a name that no longer exists and every
stack command bails out with the same generic message.
gh stack modifyalready renames a branch in git and in the stack file together(internal/modify/apply.go:190-228, verified: both
.git/gh-stackand the git branch areupdated), so the invariant is understood. This issue is about a rename performed outside
gh-stack, which is how most people rename a branch.
Related but distinct: #137 reaches the same stranded state through
sync --prune(branch deleted, stack entry left behind), and #193 is the same family of "git operations
performed outside gh-stack aren't observed".
Reproduction
Requires an
originremote, but the repository need not exist.gh stack initwith no arguments errors with "interactive input required", so the branchname is passed explicitly to keep the repro scriptable.
Observed
.git/gh-stackis byte-identical before and after the rename; it still records"branch": "feat/test".gh stack view✗ current branch "feat/test-1" is not part of a stackgh stack add feat/test-2gh stack unstack/unstack --localgh stack checkout feat/test(old name)✗ failed to checkout feat/test: failed to run git: error: pathspec 'feat/test' did not match any file(s) known to gitgh stack checkout feat/test-1(new name)✗ no locally tracked stack found for "feat/test-1"gh stack unstack <n> --localwould remove the entry, but a stack that has not beensubmitted has no stack number (
Number int \json:"number,omitempty"``,internal/stack/stack.go:46), so it cannot be targeted:
With no
gh stack list(#150) and an interactive-only checkout picker, the ways out arerenaming the branch back (verified: this fully restores the stack) or editing
.git/gh-stackby hand.Expected
Diagnose instead of denying. Before printing "is not part of a stack"
(cmd/utils.go:234-243), check whether a recorded stack references a branch that no
longer exists.
git.BranchExistsis already used throughout (cmd/sync.go:413,cmd/modify.go:315, …).
checkoutshould also stop surfacing git's rawpathspec ... did not matcherror.Leave an escape hatch. Removing or repairing a stack whose branches are missing
should not require a stack number — this is the part gh stack sync --prune for a completed stack deletes the branch but leaves stack in gh stack checkout metadata #137 also runs into.
Offer to repair. git records the rename in the reflog:
so the stack file can be updated after confirming with the user. Reflog entries expire,
so this complements 1 rather than replacing it.
I have a patch implementing 1 and 3 and will open a PR referencing this issue.
Environment
gh stackv0.1.0