#!/usr/bin/env bash set -e # usage: clean-branches # Deletes any local branches which are ancestors of origin/main, # and also any branches in origin which are ancestors of # origin/main and are named like $USER-*. # usage: clean-branches --reviews # Deletes all the above mentioned branches as well as branches # created by the scripts like `fetch-rebase-pull-request`. Be careful # as this would also remove other branches with names like review-* review=0 if [ $# -ne 0 ] && [ "$1" == "--reviews" ]; then review=1 fi push_args=() function is_merged() { ! git rev-list -n 1 origin/main.."$1" | grep -q . } function clean_ref() { ref="$1" case "$ref" in */main | */HEAD) return ;; refs/heads/review-*) if [ $review -ne 0 ]; then echo -n "Deleting local branch ${ref#refs/heads/}" echo " (was $(git rev-parse --short "$ref"))" git update-ref -d "$ref" fi ;; refs/heads/*) if is_merged "$ref"; then echo -n "Deleting local branch ${ref#refs/heads/}" echo " (was $(git rev-parse --short "$ref"))" git update-ref -d "$ref" fi ;; refs/remotes/origin/$USER-*) if is_merged "$ref"; then remote_name="${ref#refs/remotes/origin/}" echo -n "Deleting remote branch $remote_name" echo " (was $(git rev-parse --short "$ref"))" # NB: this won't handle spaces in ref names push_args=("${push_args[@]}" ":$remote_name") fi ;; esac } if [ "$(git symbolic-ref HEAD)" != 'refs/heads/main' ]; then echo "Check out main before you run this script." >&2 exit 1 fi git fetch --prune origin eval "$(git for-each-ref --shell --format='clean_ref %(refname);')" if [ "${#push_args}" -ne 0 ]; then git push origin "${push_args[@]}" fi