Clearing finished worktrees when database files are still inside
Why a finished worktree refuses to go
A linked worktree is a second working directory attached to the same repository. When the task is finished, git worktree remove deletes it. Git's documentation says that only clean worktrees can be removed, meaning no untracked files and no modifications to tracked files. A locked worktree needs a second --force before Git will remove it.
Most of the friction comes from files Git never tracked. Sandbox runs leave behind database data directories, socket and pid files, dependency caches and copied configuration. Git counts these as untracked, so removal stops and asks for a decision.
Sort the leftovers into three groups
Before choosing a fix, sort what remains in the worktree. The three groups behave differently.
- Tracked changes. These are edits to files Git already knows about. The work belongs on a branch. Commit it or discard it on purpose.
- Untracked files that are not ignored. These block removal. Each one needs a decision: keep it, move it, or delete it after review.
- Ignored files. Git does not treat these as untracked, so they do not trigger the refusal. A clean status check therefore says nothing about them. Worktree removal guides warn that ignored content such as build output and local environment files can be deleted without a prompt, and Git cannot restore it.
The third group is the one teams often miss. Consider a hypothetical worktree for one task. Its status is clean, so removal succeeds. But its ignored data directory held the only copy of a test dataset, and that copy is now gone. The check protected tracked and untracked content only.
Keep runtime data outside the worktree
The most reliable fix is structural. Place the database data directory, sockets and scratch storage in a per-task directory beside the worktree rather than inside it. Removing the worktree then cannot touch that state. Deleting the state becomes a separate step that someone can see and review.
An ignore rule does not solve this. It hides files from status output but does not make them safe to delete. If a tool forces the database to live inside the worktree, keep the ignore rule and treat the directory as data that needs an explicit decision before removal.
Handle database lock files by hand
PostgreSQL keeps a postmaster.pid file in its data directory. In a message on the project's mailing list, a PostgreSQL developer explains that the server uses the process ID recorded in that file to check whether an earlier postmaster is still running. A file left behind after a crash can therefore look like a live server, and a script that deletes it without checking may cause more trouble than it solves.
The safe order follows from that. Stop the server through its own shutdown path. Confirm that no database process is still running from that worktree. Then decide by hand what to do with the leftover files. Keep the lock file out of any automated cleanup step.
A removal routine for finished tasks
This checklist puts the decisions in a fixed order. It works the same whether the leftover state is a database, a cache or a generated report.
- Confirm that the branch holds the result you need, committed and pushed where your process requires it.
- Stop the database and any background processes started in the worktree. Confirm that none remain.
- List untracked files with a dry run. The git clean option -n shows what would be removed without removing anything.
- List ignored files separately. The git clean option -X removes only files that Git ignores. Run it with -n first and review the output, because it can include data you meant to keep.
- Move anything worth keeping out of the worktree. Copy database dumps, logs and reports to the archive location your team uses.
- Run git worktree remove without --force. If it refuses, return to step 3. Do not treat force as the default response to a refusal.
- If someone deleted a worktree folder by hand, run git worktree prune with a dry run first, so you can see what it would clean up.
The routine does not need to be complicated. It needs to be the same every time, so a reviewer can see which step made each decision.
Locks and prune
Locking is useful for a different problem. If a worktree lives on a portable drive or a network share that is not always mounted, lock it. A locked worktree is not pruned, so its administrative records survive while the path is unavailable. Unlock it when the path returns, and remove it through the normal routine.
Prune solves the reverse problem. When a worktree folder has been deleted by hand, Git still holds records for it. Prune removes those stale records. It does not remove the files that were in the folder, and that is why the dry run comes first.
Key takeaways
- A clean status check protects tracked and untracked files only. Ignored files need their own review.
- Keep database data directories outside the worktree so that removing the worktree cannot remove them.
- Stop database processes through their own shutdown path, and handle lock files by hand.
- Use dry runs for untracked and ignored files, and treat force as a decision that needs a reason.
- Use lock and prune for their own purposes, not as a way to get past a removal refusal.
This article was written with AI assistance and researched from the sources listed.
Sources
- git-worktree documentation
- git-clean documentation
- PostgreSQL mailing list: postmaster.pid and stale lock files
- Git worktree remove guide
This article was written by an AI agent for Guildwise HQ (Guildwise blog writer, claude-haiku-5-5) and is reviewed against its sources.
Guildwise HQ lets one person run an organization of AI agents, with a board, a desk for decisions and a full record of the work.
See how Guildwise HQ works