Delete remote and local branches that have been merged into master. Run after every merge to keep the repo to master-only. Supports both git-push deletion and GitHub API deletion (when git push --delete returns 403 due to proxy restrictions).
Install
npx skillscat add strikersam/autonomous-ai-agency/branch-cleanup Install via the SkillsCat registry.
Skill: branch-cleanup
When to Use
Run this skill:
- After merging any feature/fix branch into master
- After a release, when multiple branches have been absorbed
- Any time
git branch -ashows branches beyondmasterandgh-pages
Protected branches — never delete:
mastergh-pages(GitHub Pages deployment)
Step 1 — Confirm master is up to date
git fetch origin
git statusMake sure you are on master and Your branch is up to date with 'origin/master'.
If not, push first before touching branches.
Step 2 — List all remote branches
git branch -r | grep -v 'origin/master\|origin/gh-pages\|origin/HEAD'For each branch listed, check whether it is fully merged:
git log origin/master..origin/<branch-name> --oneline- Empty output → fully merged, safe to delete.
- Commits listed → unmerged work; merge it into master first (see Step 3), then return here.
Step 3 — Merge any unmerged branches (if needed)
For each branch with unmerged commits:
git merge --no-ff origin/<branch-name> -m "Merge branch '<branch-name>'"Resolve any conflicts (keep HEAD for code files; merge both sides for docs/changelog.md).
Run tests before committing the merge:
pytest -x -qThen push:
git push origin masterStep 4 — Delete merged branches
Option A — git push (standard)
git push origin --delete <branch-name>Repeat for every merged branch. If this returns 204 or succeeds, you are done.
Option B — GitHub API (use when git push --delete returns 403)
This happens when the git remote is proxied and lacks delete-refs permission.
Requires a GitHub PAT with repo scope (or delete_head_branch permission).
curl -s -o /dev/null -w "%{http_code}" -X DELETE \
-H "Authorization: token <GITHUB_PAT>" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/<owner>/<repo>/git/refs/heads/<branch-name>"Expected response: 204 (success). Any other code means failure — check PAT permissions.
To delete all merged branches in one pass:
REPO="<owner>/<repo>"
PAT="<GITHUB_PAT>"
for branch in <branch1> <branch2> <branch3>; do
status=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE \
-H "Authorization: token $PAT" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/$REPO/git/refs/heads/$branch")
[ "$status" = "204" ] && echo "✓ deleted $branch" || echo "✗ failed $branch (HTTP $status)"
doneOption C — Delete local tracking refs after remote deletion
git fetch --prune
git branch -d <branch-name> # safe delete (refuses if unmerged)Step 5 — Verify
git fetch --prune
git branch -aExpected output contains only:
* master
remotes/origin/master
remotes/origin/gh-pagesStep 6 — Security note on PATs
If a GitHub PAT was shared or pasted in plaintext during this session:
Revoke and regenerate it immediately at https://github.com/settings/tokens.
Never commit a PAT to the repository.
Automation — post-merge hook (optional)
To trigger this automatically after every successful push to master, add to.claude/hooks/post-push.sh (create if it doesn't exist):
#!/usr/bin/env bash
# After pushing master, delete the branch we just merged from (if set).
if [ -n "$MERGED_BRANCH" ]; then
git push origin --delete "$MERGED_BRANCH" 2>/dev/null || \
curl -s -X DELETE \
-H "Authorization: token $GITHUB_PAT" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/$GITHUB_REPO/git/refs/heads/$MERGED_BRANCH"
fiSet MERGED_BRANCH before pushing:
MERGED_BRANCH=claude/my-feature git push origin masterAcceptance Checks
-
git branch -ashows onlymasterandgh-pageson remote - All merged branches confirmed empty (
git log origin/master..origin/<b>returns nothing) - Any PAT used in plaintext has been revoked and regenerated
-
pytest -x -qstill green after all merges