Found while reviewing PR #110. Pre-existing, not that PR's, and host hygiene rather than a product defect — but it accumulates without bound and nothing prunes it.
What happens
tests/bash/test-e2e-subtree-check.sh creates a temporary worktree under /tmp/e2e-subtree-check.* and removes it in a cleanup trap. The trap guards on [ -d $wt ].
Once /tmp is reaped — reboot, tmpfiles, or a cleaner — the directory is gone, so the guard is false and the trap skips cleanup. The git administrative entry survives in .git/worktrees/, pointing at a path that no longer exists.
git worktree list in this repo currently holds 37 such entries.
Why the guard is the wrong shape
The directory's absence is exactly the case that needs git worktree remove (or prune), not the case that can skip it. The guard tests for the wrong thing: it should be conditioned on the worktree having been registered, not on the directory still existing.
Done when
- The trap removes the git entry whether or not the directory survives —
git worktree remove --force falling back to git worktree prune, or registering under a path the test owns and cleans unconditionally.
- The 37 existing entries are pruned.
- A test asserts that killing the directory out from under the trap still leaves no entry behind — otherwise this regresses silently, which is how it got to 37.
Found while reviewing PR #110. Pre-existing, not that PR's, and host hygiene rather than a product defect — but it accumulates without bound and nothing prunes it.
What happens
tests/bash/test-e2e-subtree-check.shcreates a temporary worktree under/tmp/e2e-subtree-check.*and removes it in a cleanup trap. The trap guards on[ -d $wt ].Once
/tmpis reaped — reboot, tmpfiles, or a cleaner — the directory is gone, so the guard is false and the trap skips cleanup. The git administrative entry survives in.git/worktrees/, pointing at a path that no longer exists.git worktree listin this repo currently holds 37 such entries.Why the guard is the wrong shape
The directory's absence is exactly the case that needs
git worktree remove(orprune), not the case that can skip it. The guard tests for the wrong thing: it should be conditioned on the worktree having been registered, not on the directory still existing.Done when
git worktree remove --forcefalling back togit worktree prune, or registering under a path the test owns and cleans unconditionally.