anthropics / anthropics/claude-code

Archiving a desktop session never deletes its worktree when the PR was squash-merged

Đang mở
#92,061 0 bình luận 0 reaction 0 người được giao Xem trên GitHub
area:desktop bug has repro platform:macos
Ngôn ngữ chính
Python
Star
145k
Fork
23.1k
Chỉ số merge pull request
Chỉ số pull request đang chờ

Mô tả

## Environment
- Claude Code 2.1.260, desktop app 1.46388.1 (macOS, Code tab)
- Worktree root configured outside the repo; also reproduces with the default in-repo location

## Expected
Per the docs, archiving a session removes its worktree ("To remove a worktree when you're done, hover over the session in the sidebar and click the archive icon").

## Actual
For repos where PRs are squash-merged (our org default, and GitHub's most common merge strategy), the worktree survives archiving in practically every case. Over weeks this accumulated ~25 leftover worktrees / ~13 GB (each carries its own node_modules and build output).

## Root cause (from inspecting local state)
Cleanup appears to run a safety check equivalent to "branch has commits not on the default branch". Squash-merging rewrites history, so the session branch always looks unmerged by commit ancestry, and the check keeps the worktree, even though:
- the PR is merged (the app itself shows prState MERGED on the session), and
- the branch's upstream is deleted, i.e. `git branch -v` shows `[gone]` after `git fetch --prune`.

Example from `git-worktrees.json` + on disk: an archived session's worktree remained with its branch at 2 commits "ahead" of main that are all contained in a squash-merge commit. Worktrees whose branches happened to be ancestry-merged were correctly deleted, confirming the cleanup path itself works.

## Consequences
- The documented archive behavior effectively never fires for squash-merge workflows.
- The untracked-dir GC does not help either: leftover worktrees stay leased/protected and get recycled into new sessions, which refreshes their protection indefinitely.
- New sessions silently reuse the stale directories (fine per se, but it masks the leak and the sidebar briefly shows a different worktree name than the one actually leased, which is confusing).

## Suggested fix
When deciding whether a worktree is safe to delete, treat the branch as merged if any of:
1. The session's tracked PR state is MERGED (the app already has this signal), or
2. The branch's upstream is gone after a pruning fetch (the standard squash-merge heuristic), or
3. Commit ancestry says merged (current check).

Uncommitted/untracked changes should of course still block deletion.

## Repro
1. In a repo whose PRs are squash-merged, start a desktop session in a worktree, commit, push, open a PR.
2. Squash-merge the PR (remote branch deleted).
3. Archive the session.
4. The worktree directory and local branch remain; `git log main..` shows the squashed commits, `git branch -v` shows `[gone]`.

Hướng dẫn đóng góp

Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này

Hướng nghiên cứu

Trace the archive cleanup safety check and its handling of the session's prState MERGED and deleted upstream, using git-worktrees.json and the git branch -v/fetch --prune state from the reproduction. Reproduce a squash-merged session, then verify that archiving removes its worktree while uncommitted or untracked changes still block deletion.

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, python
Lĩnh vực
desktop-dev, devtools
Loại issue
Lỗi
Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức độ hoạt động
Sôi nổi
Độ rõ ràng
Khá rõ ràng
Mức phù hợp với người mới
68/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.