Testing: Stale Branch Cleanup
Complete testing guide for stale branch cleanup automation.
Workflow: cleanup-stale-branches.yml
Test Script: test-cleanup-branches.sh
Quick Start
Run Tests (Dry-Run, No Changes)
# Default: shows what would be deleted (14 days old)
./.github/workflows/test-cleanup-branches.sh
# Custom: branches older than 30 days
./.github/workflows/test-cleanup-branches.sh --days 30
# Against different remote
./.github/workflows/test-cleanup-branches.sh --remote upstreamTest Options
./.github/workflows/test-cleanup-branches.sh [OPTIONS]
Options:
--days N Number of days; branches older than N are candidates
Default: 14 days
Range: 1-365 days
--remote R Git remote to inspect/delete from
Default: origin
--apply DELETE stale branches (use only in sandbox/test repos!)
Default: dry-run (no changes)
--dry-run Print actions without deleting (explicit flag)
--help Show helpWhat Gets Tested
The test script:
✅ Identifies stale branches
- Finds branches older than N days
- Checks last commit date
- Excludes protected branches (main, dev, etc.)
- Excludes currently checked-out branch
✅ Validates branch safety
- Won't delete protected branches
- Won't delete if local changes exist
- Shows which branches would be deleted
✅ Provides dry-run output
- Shows exact branches to be deleted
- Shows last commit date
- Shows time since last activity
- Shows branch creator
Expected Output (Dry-Run)
Analyzing branches older than 14 days...
Remote: origin
Mode: dry-run (no changes)
Would delete these branches:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Branch Name Last Commit Days Old
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
fix/old-bug 2025-12-25 22 days
feature/deprecated-ui 2025-12-20 27 days
wip/experiment 2025-12-15 32 days
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Total branches to delete: 3
To apply changes, run:
./.github/workflows/test-cleanup-branches.sh --days 14 --applyUsage Examples
Example 1: Check Stale Branches (Safe, Read-Only)
# Show branches not touched in 14 days
./.github/workflows/test-cleanup-branches.sh
# Show branches not touched in 30 days
./.github/workflows/test-cleanup-branches.sh --days 30Example 2: Dry-Run Cleanup
# Preview what WOULD be deleted (14 days, no changes)
./.github/workflows/test-cleanup-branches.sh --dry-run
# Preview with custom threshold (21 days)
./.github/workflows/test-cleanup-branches.sh --days 21 --dry-runExample 3: Apply Cleanup (Destructive!)
# ⚠️ ACTUALLY DELETE branches 14+ days old
# (only use in test repos!)
./.github/workflows/test-cleanup-branches.sh --apply
# Delete branches 21+ days old
./.github/workflows/test-cleanup-branches.sh --days 21 --applyExample 4: Check Different Remote
# Analyze upstream instead of origin
./.github/workflows/test-cleanup-branches.sh --remote upstream
# Delete from upstream (destructive!)
./.github/workflows/test-cleanup-branches.sh --remote upstream --applyProtected Branches
The script never deletes:
maindevmasterproduction- Currently checked-out branch
- Branches with uncommitted changes
Why? Prevents accidental data loss.
Troubleshooting
"No branches found"
All branches are either:
- Newer than threshold
- Protected branches
- Currently checked out
Try a higher threshold:
./.github/workflows/test-cleanup-branches.sh --days 7"Permission denied"
The script needs push access to delete branches:
# Check authentication
git remote -v
# Test push access
git fetch origin # Should workIf you get permission errors:
# Ensure you have push access to remote
git remote set-url origin https://github.com/USERNAME/REPO.git
git push origin --dry-run"Could not remove branch"
Branch might be:
- Protected (check GitHub settings)
- Has uncommitted changes
- PR still open from that branch
- Force-pushed or deleted remotely
"Wrong remote"
# List available remotes
git remote -v
# Use correct remote
./.github/workflows/test-cleanup-branches.sh --remote <remote-name>Safety Checklist
Before running --apply:
- [ ] Run
--dry-runfirst - [ ] Review branches to be deleted
- [ ] Confirm none are needed
- [ ] Test on non-critical repo first
- [ ] Ensure backups exist (GitHub keeps deleted branches briefly)
- [ ] Have commit history backed up
Workflow (Automated)
The cleanup-stale-branches.yml workflow:
Triggers: Schedule (weekly)
Actions:
- Fetches all branches
- Identifies branches older than threshold
- Posts PR or comment with summary
- Can be configured to auto-delete
Configuration:
DAYS_THRESHOLD: 14 (customize in workflow)PROTECTED_BRANCHES: main, dev, production, masterAUTO_DELETE: false (default is dry-run)
Cost
Free! Uses GitHub's built-in Git operations.
✅ No API charges
✅ No storage impact
✅ Git cleanup is fast
Recovery
If you accidentally delete a branch:
# GitHub keeps deleted branches in reflog for ~3 months
# Contact GitHub Support: https://github.com/contact
# Or check local backup
git reflog # Shows all branch operationsAdvanced: Custom Branch Protection
To protect additional branches from deletion:
Edit: .github/workflows/test-cleanup-branches.sh
Find this line:
PROTECTED_BRANCHES=("main" "dev" "production" "master")Add your branch:
PROTECTED_BRANCHES=("main" "dev" "production" "master" "staging" "my-branch")Recommendations
Suggested Settings:
- Weekly cleanup: Remove branches > 30 days old
- Monthly cleanup: Remove branches > 60 days old
- Always dry-run first before applying
- Review deleted branches in GitHub activity log
Example Workflow Schedule:
# Every Monday at 2 AM UTC
schedule:
- cron: '0 2 * * 1'See Also
- Workflows Overview - All workflows
- Git Documentation - Git reference