|
| 1 | +--- |
| 2 | +name: cleanup |
| 3 | +description: Git branch hygiene - delete merged/closed branch, prune stale refs, sync dependencies |
| 4 | +user_invocable: true |
| 5 | +triggers: |
| 6 | + - /cleanup |
| 7 | +--- |
| 8 | + |
| 9 | +# Git Cleanup Skill |
| 10 | + |
| 11 | +Automates git branch hygiene after merging or closing PRs. Safely deletes merged branches (and force-deletes closed/abandoned branches), prunes stale remote tracking refs, syncs dependencies, and runs garbage collection. |
| 12 | + |
| 13 | +## Workflow |
| 14 | + |
| 15 | +Execute these steps in order: |
| 16 | + |
| 17 | +### 1. Check current branch |
| 18 | + |
| 19 | +```bash |
| 20 | +git branch --show-current |
| 21 | +``` |
| 22 | + |
| 23 | +Store the result as `CURRENT_BRANCH`. |
| 24 | + |
| 25 | +### 2. Guard against main/master |
| 26 | + |
| 27 | +If `CURRENT_BRANCH` is `main` or `master`: |
| 28 | +- Report: "Already on main branch. No branch to clean up." |
| 29 | +- Skip to step 7 (pull latest) and continue from there. |
| 30 | + |
| 31 | +### 3. Check for uncommitted changes |
| 32 | + |
| 33 | +```bash |
| 34 | +git status --porcelain |
| 35 | +``` |
| 36 | + |
| 37 | +If output is non-empty: |
| 38 | +- Warn the user: "You have uncommitted changes. Please commit or stash them first." |
| 39 | +- Stop and do not proceed. |
| 40 | + |
| 41 | +### 4. Check if branch is merged or closed |
| 42 | + |
| 43 | +First check for merged PRs: |
| 44 | +```bash |
| 45 | +gh pr list --state merged --head CURRENT_BRANCH --json number |
| 46 | +``` |
| 47 | + |
| 48 | +If merged, proceed to step 5. |
| 49 | + |
| 50 | +If not merged, check for closed PRs: |
| 51 | +```bash |
| 52 | +gh pr list --state closed --head CURRENT_BRANCH --json number |
| 53 | +``` |
| 54 | + |
| 55 | +If closed (result is non-empty): |
| 56 | +- Report: "Branch 'CURRENT_BRANCH' has a closed (unmerged) PR. Proceeding with deletion." |
| 57 | +- Proceed to step 5 (will use force delete in step 6). |
| 58 | + |
| 59 | +If neither merged nor closed: |
| 60 | +- Check if the branch is merged locally: `git branch --merged main | grep -w CURRENT_BRANCH` |
| 61 | +- If not merged anywhere, warn: "Branch 'CURRENT_BRANCH' does not appear to be merged or closed. Use `git branch -D` manually if you want to force delete." |
| 62 | +- Stop and do not proceed. |
| 63 | + |
| 64 | +Store whether the branch was `MERGED` or `CLOSED` for use in step 6. |
| 65 | + |
| 66 | +### 5. Switch to main |
| 67 | + |
| 68 | +```bash |
| 69 | +git checkout main |
| 70 | +``` |
| 71 | + |
| 72 | +### 6. Delete the branch |
| 73 | + |
| 74 | +If branch was `MERGED`: |
| 75 | +```bash |
| 76 | +git branch -d CURRENT_BRANCH |
| 77 | +``` |
| 78 | + |
| 79 | +If branch was `CLOSED` (PR closed without merging): |
| 80 | +```bash |
| 81 | +git branch -D CURRENT_BRANCH |
| 82 | +``` |
| 83 | + |
| 84 | +Report: "Deleted branch CURRENT_BRANCH." (mention if force-deleted due to closed PR) |
| 85 | + |
| 86 | +### 7. Pull latest |
| 87 | + |
| 88 | +```bash |
| 89 | +git pull origin main |
| 90 | +``` |
| 91 | + |
| 92 | +### 8. Prune remote tracking refs |
| 93 | + |
| 94 | +```bash |
| 95 | +git fetch --prune |
| 96 | +``` |
| 97 | + |
| 98 | +### 9. Delete stale local branches |
| 99 | + |
| 100 | +Find and delete local branches whose upstream is gone: |
| 101 | + |
| 102 | +```bash |
| 103 | +git for-each-ref --format '%(refname:short) %(upstream:track)' refs/heads | while read branch track; do |
| 104 | + if [ "$track" = "[gone]" ]; then |
| 105 | + git branch -d "$branch" 2>/dev/null && echo "Deleted stale branch: $branch" |
| 106 | + fi |
| 107 | +done |
| 108 | +``` |
| 109 | + |
| 110 | +Report any branches deleted. |
| 111 | + |
| 112 | +### 10. Sync dependencies |
| 113 | + |
| 114 | +Detect package manager and sync: |
| 115 | + |
| 116 | +- If `uv.lock` exists: `uv sync` |
| 117 | +- Else if `bun.lockb` exists: `bun install` |
| 118 | +- Else if `package-lock.json` exists: `npm install` |
| 119 | +- Else if `requirements.txt` exists: `pip install -r requirements.txt` |
| 120 | +- Else: Skip dependency sync |
| 121 | + |
| 122 | +### 11. Git garbage collection |
| 123 | + |
| 124 | +```bash |
| 125 | +git gc --prune=now |
| 126 | +``` |
| 127 | + |
| 128 | +### 12. Summary |
| 129 | + |
| 130 | +Report completion: |
| 131 | +- Branch deleted (if applicable) |
| 132 | +- Number of stale branches pruned |
| 133 | +- Dependencies synced (which package manager) |
| 134 | +- Garbage collection complete |
| 135 | + |
| 136 | +## Error Handling |
| 137 | + |
| 138 | +- **Dirty working tree**: Stop immediately and ask user to commit/stash |
| 139 | +- **Branch not merged or closed**: Warn and stop - never force delete without explicit user request |
| 140 | +- **Branch closed (not merged)**: Force delete with `-D` since branch is abandoned |
| 141 | +- **Already on main**: Skip branch deletion, continue with pull/prune/gc |
| 142 | +- **No remote**: If `git pull` fails due to no remote, continue with local operations |
| 143 | +- **gh CLI not available**: Fall back to `git branch --merged` check |
0 commit comments