anthropics / anthropics/claude-code

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

Abierto
#92,061 0 comentarios 0 reacciones 0 asignados Ver en GitHub
area:desktop bug has repro platform:macos
Lenguaje dominante
Python
Estrellas
145k
Forks
23.1k
Métricas de merge de PR
Métricas de PR pendientes

Descripción

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

Guía de contribución

No hay ninguna guía de contribución indexada para este repositorio

Línea de trabajo

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.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
git, python
Área
desktop-dev, devtools
Tipo de issue
Error
Dificultad
4/5
Tiempo estimado
3-5 días
Estado de actividad
Activo
Claridad
Bastante claro
Aptitud para principiantes
68/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.