Removes git worktrees safely, cleans up associated branches, and pulls latest mainline after removal. Use when finished with a worktree, done with a branch, cleaning up after a merge or PR, abandoning work in a worktree, or when "git worktree list" shows stale entries. Checks for uncommitted changes, verifies no open PRs before branch deletion, and handles force-removal of locked worktrees.
90
88%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Passed
No known issues
Clean up a git worktree after work is complete (merged, PR created, or abandoned). Updates the mainline branch so local state is current.
Core principle: User-triggered only. Never automatic.
git worktree listIf multiple worktrees exist (beyond the main working tree), present the list and ask which to clean up.
If only one non-main worktree exists, confirm: "Remove worktree at <path>?"
git -C <worktree-path> status --porcelainIf dirty:
⚠️ CRITICAL — cd before removal: You MUST determine the main working tree path and cd to it BEFORE running any removal command. Always chain the cd and removal in the SAME Bash call using &&. Never run them as separate Bash tool calls — shell CWD persists between calls, but a deleted CWD will brick every subsequent command.
First, capture the main working tree path from Step 1's output (the first entry in git worktree list).
Then remove:
cd <main-working-tree> && git worktree remove <worktree-path>If removal fails (e.g., locked or dirty), try with --force after informing your human partner:
cd <main-working-tree> && git worktree remove --force <worktree-path>If the worktree directory was already manually deleted from disk, clean up stale metadata:
cd <main-working-tree> && git worktree pruneIf any Bash command fails with Path "..." does not exist, your shell CWD has been deleted from disk. Do NOT retry the same command. You MUST prefix your next command with an absolute cd:
cd <main-working-tree> && git worktree prune && git worktree listThe main working tree path (first entry from Step 1) is always valid. Use that. Retrying without the cd prefix will fail infinitely.
If the worktree's branch has been merged or your human partner chose "discard":
git branch -d <branch-name> # safe delete (only if merged)If not merged and user wants to delete:
git branch -D <branch-name> # force delete — confirm firstCheck for open PRs before deleting:
gh pr list --head <branch-name> --state open --json number --jq 'length'If the result is non-zero, skip branch deletion — the branch is still needed for the open PR.
Determine the mainline branch:
git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@'Fallback: check for main then master.
If currently on mainline:
git pull --autostashIf --autostash fails or there are staged changes:
git stash
git pull --ff-only
git stash popIf pull can't fast-forward: inform your human partner. Do not force-merge or rebase without asking.
If NOT on mainline: offer to switch.
Would you like to switch to <mainline> and pull latest?Never:
git worktree remove without cd <main-tree> && prefix in the same commandcd-ing to a valid absolute path — if you get "Path does not exist", your CWD is goneAlways:
cd <main-working-tree> && before every removal/prune command| Command | Purpose |
|---|---|
git worktree list | List all worktrees |
git -C <path> status --porcelain | Check for uncommitted changes |
git worktree remove <path> | Remove a worktree |
git worktree remove --force <path> | Force-remove (locked/dirty worktree) |
git worktree prune | Clean up stale worktree metadata |
git branch -d <branch> | Safe-delete merged branch |
git branch -D <branch> | Force-delete unmerged branch |
gh pr list --head <branch> --state open --json number --jq 'length' | Check for open PRs on branch |
Pairs with:
a01bac9
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.