Skip to content

fix(server): storage cleanup judges each repository in a multi-repo worktree - #354

Merged
LoganRupe merged 1 commit into
multi-repo-workspacesfrom
bug/storage-cleanup/multi-repo-containers
Oct 23, 2026
Merged

LoganRupe merged 1 commit into
multi-repo-workspacesfrom
bug/storage-cleanup/multi-repo-containers

Conversation

@LoganRupe

@LoganRupe LoganRupe commented Oct 23, 2026 •

Copy link
Copy Markdown
Owner

Problem

In the multi-repo fork, storage cleanup could delete uncommitted work. When the project root is itself a repo with the others cloned inside it and gitignored (the layout kieron describes in pingdotgg#7041), a new-worktree run puts the nested worktrees inside the root's worktree. Cleanup only looked at the root: no changes there, no commits beyond main, so with "Delete unchanged worktrees" (or "Delete worktrees with deleted threads") it ran git worktree remove on the root and took backend/ with its uncommitted files. A container without a root repo had the opposite problem and was never collected.

Change

When a thread's worktree is a multi-repo container, cleanup reads its layout file and runs the existing checks on each repository's worktree: linked worktree, branch, local changes, submodules, its own default branch (so a develop repo is judged against develop), and its own pull request. The container goes only when every repository passes, through WorkspaceWorktrees.remove, so nested worktrees are removed first and files the user left in a plain container stay. Keep reasons name the repository, e.g. "Has uncommitted changes (1 file) in backend". Single-repo worktrees go through the same path as before.

Under "Delete merged worktrees", a repository the run never committed to counts as done once another repository's PR is merged, otherwise a root repo that never gets commits would block cleanup forever.

Scope and approval

Fork-only fix for a data-loss bug in the multi-repo feature, raised in pingdotgg#7041 (discussion comment 19133258). The upstream bug for hand-nested worktrees, pingdotgg#23866, is separate: without a layout file there is nothing to read, so this doesn't fix it.

Not covered: resuming a thread whose container was cleaned up recreates only the root worktree. Deleting a container by hand already has the same gap; that's a follow-up.

Verification

Four new tests in storageCleanup.test.ts: root repo with uncommitted work in a nested worktree is kept, each repo is judged against its own default branch (kept with a commit beyond develop, removed once it's pushed there), a plain container is removed along with its links, and a plain container with uncommitted work is kept. All four fail on multi-repo-workspaces and pass here. The rest of the file has 15 failing orphan-report tests that fail identically on multi-repo-workspaces without this change.

In the real app, against two dev servers (before and after), each side has a thread created through "New worktree" in a root-repo project with a gitignored backend clone and an uncommitted backend/wip.ts. Turning on "Delete unchanged worktrees" removed the container on the old build (Files then can't list backend, and wip.ts is gone from disk) and kept it on this one with "Has uncommitted changes (1 file) in backend".

Before / after video

compare.mp4

Written with Claude Opus 5.5 in Claude Code.

…orktree

A multi-repo run's container was judged as one repository. When the project root is a repo, cleanup checked only the root worktree, saw no changes (the nested repos are gitignored) and ran git worktree remove on it, deleting the nested worktrees with their uncommitted work. A container without a root repo was never collected.

Cleanup now reads the container's layout, runs every check on each repository's worktree against its own default branch and pull request, and removes the container through WorkspaceWorktrees only when all of them pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant