Use when adding new error messages to React, or seeing "unknown error code" warnings.
npx skills add Anshin-Health-Solutions/superpai --skill "clean-gone"
Install specific skill from multi-skill repository
# Description
Safely clean up local git branches whose remote tracking reference has been deleted (marked as [gone]). Handles worktree removal before branch deletion, supports a dry-run mode for previewing changes, and integrates with the git-worktrees skill.
# SKILL.md
name: clean-gone
description: Safely clean up local git branches whose remote tracking reference has been deleted (marked as [gone]). Handles worktree removal before branch deletion, supports a dry-run mode for previewing changes, and integrates with the git-worktrees skill.
triggers:
- /clean-gone
- "clean up gone branches"
- "delete merged branches"
- "prune stale branches"
- "remove gone tracking"
Clean Gone Branches
Purpose
When pull requests are merged and source branches are deleted on the remote, local branches accumulate with [gone] tracking references. Over time this creates dozens of stale branches that clutter git branch -v, make tab completion noisy, and can cause confusion about what is still active. This skill identifies all such branches, checks for associated worktrees, removes worktrees safely, then deletes the branches.
Phase 1: Update Remote State
Before identifying [gone] branches, synchronize remote state:
# Fetch all remotes and prune deleted remote-tracking references
git fetch --prune --all
# Confirm fetch succeeded and pruned refs are noted in output
# Example output: "[pruned] origin/feat/old-feature"
Never run branch cleanup without fetching first. The [gone] status is only visible after the remote tracking refs are pruned.
Phase 2: Identify [gone] Branches
List all local branches whose upstream tracking branch has been deleted:
# List branches with their upstream tracking status
git branch -vv
Sample output:
feat/auth-pkce a1b2c3d [origin/feat/auth-pkce: gone] add PKCE flow
feat/billing-refactor 9f8e7d6 [origin/feat/billing-refactor: gone] refactor billing
* main c4d5e6f [origin/main] merge auth changes
dev 3a2b1c0 [origin/dev] latest dev build
Extract only the [gone] branches:
git branch -vv | grep ': gone]' | awk '{print $1}'
Store the list for iteration:
GONE_BRANCHES=$(git branch -vv | grep ': gone]' | awk '{print $1}')
echo "Branches marked [gone]:"
echo "$GONE_BRANCHES"
Phase 3: Safety Checks
Before deleting any branch, run these safety checks for each candidate:
Check 1: Not the Current Branch
CURRENT=$(git branch --show-current)
for branch in $GONE_BRANCHES; do
if [ "$branch" = "$CURRENT" ]; then
echo "SKIP: $branch is the current branch β switch away first"
fi
done
Check 2: Fully Merged Into Main or Dev
for branch in $GONE_BRANCHES; do
if git merge-base --is-ancestor "$branch" main; then
echo "SAFE: $branch is merged into main"
elif git merge-base --is-ancestor "$branch" dev; then
echo "SAFE: $branch is merged into dev"
else
echo "WARNING: $branch has commits not in main or dev β review before deleting"
git log main.."$branch" --oneline
fi
done
If a branch has unmerged commits, report it and skip it. Do not delete unmerged branches without explicit user confirmation.
Check 3: Associated Worktrees
# List all worktrees
git worktree list
Sample output:
C:/projects/myapp c4d5e6f [main]
C:/projects/myapp-feat-auth-pkce a1b2c3d [feat/auth-pkce]
C:/projects/myapp-billing 9f8e7d6 [feat/billing-refactor]
Identify worktrees that are checked out on a [gone] branch:
git worktree list --porcelain | grep -A2 "branch refs/heads/feat/auth-pkce"
A worktree must be removed before its branch can be deleted. Git will refuse to delete a branch that has an active worktree.
Phase 4: Dry-Run Mode
Always present what will happen before taking action. Dry-run is the default mode.
echo "=== DRY RUN: No changes will be made ==="
echo ""
for branch in $GONE_BRANCHES; do
echo "Would process: $branch"
# Check for worktree
WORKTREE_PATH=$(git worktree list | grep "\[$branch\]" | awk '{print $1}')
if [ -n "$WORKTREE_PATH" ]; then
echo " -> Would remove worktree at: $WORKTREE_PATH"
fi
echo " -> Would delete branch: $branch"
done
echo ""
echo "Run with --execute to apply these changes."
Only proceed to Phase 5 when the user explicitly confirms with --execute or equivalent approval.
Phase 5: Worktree Removal
For each branch that has an associated worktree:
# Get the worktree path for a specific branch
WORKTREE_PATH=$(git worktree list | grep "\[feat/auth-pkce\]" | awk '{print $1}')
# Remove the worktree
git worktree remove "$WORKTREE_PATH"
# If the worktree has uncommitted changes, use --force only after user confirmation
git worktree remove --force "$WORKTREE_PATH"
After removal, verify:
git worktree list
# The removed worktree should no longer appear
If git worktree remove fails because the directory no longer exists on disk, use:
git worktree prune
This cleans up stale worktree metadata without requiring the directory to exist.
Phase 6: Branch Deletion
After worktrees are removed, delete the branches:
for branch in $GONE_BRANCHES; do
# Skip current branch
if [ "$branch" = "$(git branch --show-current)" ]; then
echo "SKIPPED (current): $branch"
continue
fi
# Delete merged branch (safe delete β refuses to delete unmerged)
if git branch -d "$branch" 2>/dev/null; then
echo "DELETED: $branch"
else
echo "SKIPPED (unmerged commits): $branch β use -D to force delete if intended"
fi
done
Use -d (lowercase), not -D (uppercase). The lowercase form refuses to delete branches with unmerged commits, which prevents data loss. Only escalate to -D when the user explicitly instructs it and you have confirmed the branch's commits are irrelevant.
Phase 7: Verification
After all deletions:
# Confirm no [gone] branches remain
git branch -vv | grep ': gone]'
# Should produce no output
# Show current clean branch list
git branch -v
# Verify worktrees are clean
git worktree list
Full Executable Script
#!/usr/bin/env bash
# clean-gone.sh β Remove local branches with [gone] remote tracking refs
# Usage: ./clean-gone.sh [--execute]
set -euo pipefail
EXECUTE=false
if [ "${1:-}" = "--execute" ]; then
EXECUTE=true
fi
echo "Fetching and pruning remote refs..."
git fetch --prune --all
GONE_BRANCHES=$(git branch -vv | grep ': gone]' | awk '{print $1}')
CURRENT=$(git branch --show-current)
if [ -z "$GONE_BRANCHES" ]; then
echo "No [gone] branches found. Nothing to clean."
exit 0
fi
echo ""
echo "Found [gone] branches:"
echo "$GONE_BRANCHES" | sed 's/^/ /'
if [ "$EXECUTE" = false ]; then
echo ""
echo "DRY RUN complete. Run with --execute to apply changes."
exit 0
fi
echo ""
echo "Removing worktrees and branches..."
for branch in $GONE_BRANCHES; do
if [ "$branch" = "$CURRENT" ]; then
echo "SKIP (current branch): $branch"
continue
fi
WORKTREE_PATH=$(git worktree list | grep "\[$branch\]" | awk '{print $1}' || true)
if [ -n "$WORKTREE_PATH" ]; then
echo "Removing worktree: $WORKTREE_PATH"
git worktree remove "$WORKTREE_PATH" || git worktree prune
fi
if git branch -d "$branch" 2>/dev/null; then
echo "DELETED: $branch"
else
echo "SKIPPED (unmerged): $branch"
fi
done
echo ""
echo "Done. Remaining branches:"
git branch -v
Integration with git-worktrees Skill
When the git-worktrees skill is active, call /clean-gone as part of the worktree teardown flow:
- User merges PR on GitHub
- Run
/clean-gone --dry-runto preview stale state - User approves cleanup
- Run
/clean-gone --executeto remove worktrees and branches git-worktreesskill updates its internal worktree registry
This keeps the worktree registry synchronized with actual disk and git state.
Output Format
CLEAN-GONE RESULT
Mode: DRY RUN | EXECUTED
Fetched: origin (pruned N refs)
Branches found [gone]: N
- feat/branch-one (worktree at /path/to/worktree)
- feat/branch-two (no worktree)
- feat/branch-three (SKIPPED β unmerged commits)
Actions taken:
- Removed worktree: /path/to/worktree
- Deleted branch: feat/branch-one
- Deleted branch: feat/branch-two
- Skipped branch: feat/branch-three
Remaining local branches: N
No [gone] branches remain.
Common Errors and Fixes
| Error | Cause | Fix |
|---|---|---|
error: Cannot delete branch 'X' checked out at 'Y' |
Worktree still active | Remove worktree first with git worktree remove |
error: The branch 'X' is not fully merged |
Unmerged commits | Review commits, then use git branch -D only if safe |
fatal: 'X' is not a valid branch name |
Branch name has special chars | Quote the branch name in the command |
| Worktree path no longer exists on disk | Directory was manually deleted | Run git worktree prune to clean metadata |
# Supported AI Coding Agents
This skill is compatible with the SKILL.md standard and works with all major AI coding agents:
Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.