Today, I cleaned hundreds of stale branches with (🚧 use with caution 🚧):

git for-each-ref refs/remotes/origin \
  --exclude='refs/remotes/origin/release/*' \
  --format='%(committerdate:unix) %(refname:short)' |
  awk -v cutoff="$(gdate -d '6 months ago' +%s)" '
    $1 < cutoff {
      sub("^origin/", "", $2)
      print $2
    }
  ' |
  xargs -r -n 1 echo git push --delete origin

Things to note from the command above:

  • Use --exclude to avoid deleting certain branches.
  • The --format uses a Unix timestamp so awk can compare dates numerically.
  • Notice the use of gdate from the GNU Core Utilities.
    • On macOS, install with brew install coreutils.
    • Set the date offset to control how old a branch must be before deletion.
  • The echo turns the command into a dry run so you can verify the output before deleting anything.
    • Remove echo if you want to delete directly.

If you just want to inspect branches, run:

git for-each-ref refs/remotes/origin \
  --sort=committerdate \
  --exclude='refs/remotes/origin/release/*' \
  --format='%(committerdate:short) %(refname:short)'