github / github/gh-stack

Renaming a stacked branch with `git branch -m` strands the stack: metadata keeps the old name

未關閉
#423 1 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視
feature request topic: cli - general
主要語言
Go
星號
1.5k
分支
70
平均合併
1 天 8 小時
30 天內合併 PR
7

描述

### Summary

`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.

```sh
git init repro && cd repro
git commit --allow-empty -m initial
git remote add origin https://github.com/you/does-not-exist.git
git switch -c feat/test
git commit --allow-empty -m wip

gh stack init feat/test # ✓ Adopted 1 branch: main ← feat/test
gh stack view --short # ✓ works

git branch -m feat/test-1

gh stack view # ✗ broken from here on
```

`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 --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

1. **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.

2. **Leave an escape hatch.** Removing or repairing a stack whose branches are missing
should not require a stack number — this is the part #137 also runs into.

3. **Offer to repair.** git records the rename in the reflog:

```
feat/test-1@{0}: Branch: renamed refs/heads/feat/test to refs/heads/feat/test-1
```

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 stack` v0.1.0
- macOS 24.6.0 (Darwin, arm64)

貢獻指南

開啟貢獻指南

研究方向

從 cmd/utils.go 中目前分支的錯誤開始,接著追蹤 internal/stack/stack.go 中的 resolveStack、FindAllStacksForBranch 和 Stack.Contains。檢查 git.BranchExists 的使用,以及 internal/modify/apply.go 中對重新命名的處理,包括 issue 中描述的基於 reflog 的修復。完成的標準是:能夠診斷外部重新命名的分支,並且無需 stack 編號即可修復或移除它。

由索引模型根據 Issue 內容生成。

評估

技術堆疊
git, go
領域
cli, developer-experience
Issue 類型
缺陷
難度
4/5
預估耗時
3-5 天
活躍度
冷清
描述清晰度
描述清楚
新手友好度
35/100

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。