Skip to content

Instantly share code, notes, and snippets.

@szeyu
Created October 30, 2025 09:04
Show Gist options
  • Select an option

  • Save szeyu/eb45fad02802a0cf316f724c0fd85117 to your computer and use it in GitHub Desktop.

Select an option

Save szeyu/eb45fad02802a0cf316f724c0fd85117 to your computer and use it in GitHub Desktop.
A script to quickly discover stale branch and manage it (delete)
#!/bin/bash
# Fail fast and show errors
set -euo pipefail
# --- User-editable parameters ---
REPO="${REPO:-rytbank/data-schedules}"
DAYS_OLD="${DAYS_OLD:-30}"
EXCLUDE_PATTERN="${EXCLUDE_PATTERN:-^(main|dev-env|uat-env)$}"
DEFAULT_BRANCH="${DEFAULT_BRANCH:-main}"
DRY_RUN="${DRY_RUN:-true}"
FORCE_DELETE="${FORCE_DELETE:-false}"
# --- Check for dependencies ---
if ! command -v gh >/dev/null 2>&1; then
echo "'gh' CLI not found; please install from https://cli.github.com/"
exit 1
fi
# --- Confirm authentication ---
if ! gh auth status >/dev/null 2>&1; then
echo "GitHub CLI not authenticated; run 'gh auth login'."
exit 1
fi
# --- Calculate cutoff date ---
if date -v-1d +%Y-%m-%dT%H:%M:%SZ >/dev/null 2>&1; then
# macOS/BSD date
CUTOFF_DATE=$(date -u -v-"$DAYS_OLD"d +%Y-%m-%dT%H:%M:%SZ)
else
# GNU date (Linux)
CUTOFF_DATE=$(date -u -d "$DAYS_OLD days ago" +%Y-%m-%dT%H:%M:%SZ)
fi
echo "Fetching branches for $REPO..."
branches=($(gh api "repos/$REPO/branches" --paginate --jq '.[].name'))
echo "Analyzing branches older than $CUTOFF_DATE..."
for branch in "${branches[@]}"; do
if echo "$branch" | grep -Eq "$EXCLUDE_PATTERN"; then
continue
fi
last_commit_date=$(gh api "repos/$REPO/commits/$branch" --jq '.commit.committer.date' 2>/dev/null || true)
if [[ -n "$last_commit_date" && "$last_commit_date" < "$CUTOFF_DATE" ]]; then
echo "Branch $branch is stale since $last_commit_date"
if git branch --contains "origin/$branch" | grep -q "$DEFAULT_BRANCH"; then
if [[ "$DRY_RUN" == "false" ]]; then
echo "[DELETE] $branch"
echo "$branch,$last_commit_date,DELETED" >> stale_branches.csv
# gh api -X DELETE "repos/$REPO/git/refs/heads/$branch"
else
echo "[DRY RUN] Would delete: $branch"
echo "$branch,$last_commit_date,DRY_DELETED" >> stale_branches.csv
fi
else
if [[ "$FORCE_DELETE" == "true" ]]; then
if [[ "$DRY_RUN" == "false" ]]; then
echo "[FORCE DELETE] $branch"
echo "$branch,$last_commit_date,FORCE_DELETED" >> stale_branches.csv
# gh api -X DELETE "repos/$REPO/git/refs/heads/$branch"
else
echo "[DRY RUN] Would force delete: $branch"
echo "$branch,$last_commit_date,DRY_FORCE_DELETED" >> stale_branches.csv
fi
else
echo "[SKIP] $branch not merged into $DEFAULT_BRANCH"
echo "$branch,$last_commit_date,SKIPPED" >> stale_branches.csv
fi
fi
fi
done
echo "Done"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment