anthropics / anthropics/claude-code

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

Offen
#92,061 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
area:desktop bug has repro platform:macos
Vorherrschende Sprache
Python
Sterne
145k
Forks
23.1k
PR-Merge-Kennzahlen
PR-Kennzahlen ausstehend

Beschreibung

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

Beitragsleitfaden

Für dieses Repository ist kein Beitragsleitfaden indexiert

Rechercherichtung

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.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
git, python
Bereich
desktop-dev, devtools
Issue-Typ
Bug
Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Aktivitätsstatus
Aktiv
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
68/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.