`gh stack checkout` reports "Local stack matches remote" without comparing local branch refs
- Ngôn ngữ chính
- Go
- Star
- 1.5k
- Fork
- 70
- Merge trung bình
- 1 ngày 8 giờ
- Pull request đã merge (30 ngày)
- 7
Mô tả
## Summary
`gh stack checkout` reports `✓ Local stack matches remote` when a local branch has diverged from its remote counterpart. It appears to compare its recorded state against the remote, and never against the actual local branch refs — so a local branch that has moved is invisible to the check.
```
$ git rev-parse --short=10 stack-b-two # local
df863cea57
$ git rev-parse --short=10 origin/stack-b-two # remote, one commit ahead
41fd74d3ae
$ gh stack checkout 6
✓ Local stack matches remote — switching to branch (stack #6)
ℹ Already on stack-b-two
$ gh stack view --short # no warning, no ⚠ Needs rebase
Stack #6
» stack-b-two ○ #5 (current)
├ stack-b-one ○ #4
└ main
```
The extension's own state file held the **correct** value the whole time:
```
$ jq -r '.stacks[].branches[] | select(.branch=="stack-b-two") | .head' .git/gh-stack
41fd74d3ae... # matches the remote; the local ref is what diverged
```
So this is not stale metadata. Recorded state and remote agreed, the local ref disagreed with both, and nothing compared against it.
## Why this matters
This is the reassurance a user sees immediately before #380 destroys their work. In that state `gh stack push` rewinds the remote branch and the commits become unreachable — and if the branch loses its only commit, GitHub auto-closes the PR with no files. The sequence is:
```
gh stack checkout -> "✓ Local stack matches remote"
gh stack push -> "✓ Pushed N branches" (remote commits gone, PR closed)
```
Fixing #380 addresses the destruction. Fixing this addresses the false confidence that leads someone to run the command in the first place.
## How a local branch gets behind
Anything not mediated by the extension. A plain `git fetch` after a colleague pushes; CI committing to the PR head branch (the trigger in #380); or building a change in a `git worktree` and pushing it with `git push origin :`, which moves the remote and leaves the local branch untouched.
## Reproduction
Against a stack whose branches are in sync:
```bash
git switch
git reset --hard HEAD~1 # simulate the local branch falling behind
gh stack checkout # -> "✓ Local stack matches remote"
gh stack view --short # -> no warning
```
Public repo with two stacks set up for this: https://github.com/xn/gh-stack-repro
## Expected
Compare recorded/remote heads against the actual local branch refs. On divergence, say so and name the fix (`git branch -f origin/`), rather than reporting a match.
A `gh stack status` / `gh stack doctor` surfacing per-branch local-vs-remote drift would cover the general case, since plain git will always be able to desync the extension's state.
## Environment
- `gh` 2.97.0
- `gh-stack` v0.1.0
- git 2.50.1
- macOS 26.4.1, darwin/arm64
## Related
- #380 — the data loss this false reassurance leads into.
- #193 — handling rebases performed outside `gh stack`; same general gap (external git operations invisible to the extension).
Hướng dẫn đóng góp
Hướng nghiên cứu
Bắt đầu từ lệnh `gh stack checkout` và lần theo bước kiểm tra báo cáo `Local stack matches remote`; chạy trường hợp tái hiện được cung cấp sau khi di chuyển một ref của branch cục bộ bằng `git reset --hard`. Hoàn tất khi lệnh so sánh các head đã ghi nhận hoặc head từ remote với các ref cục bộ thực tế, cảnh báo khi có sai lệch và nêu cách khắc phục được đề xuất bằng `git branch -f`.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- git, go
- Lĩnh vực
- cli
- Loại issue
- Lỗi
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức độ hoạt động
- Ít trao đổi
- Độ rõ ràng
- Khá rõ ràng
- Mức phù hợp với người mới
- 55/100