2 Remove old Git branches
Philip edited this page 2025-03-20 10:02:57 +13:00

This script removes git branches without an upstream (removed or non-existant). Read more at the corresponding blog post.

#!/bin/bash

while [[ $# -gt 0 ]]; do
    case $1 in
        -h|--help)
            echo "This script lists Git branches whose upstream tracking branches no longer exist (are \"[gone]\") and that have no upstream tracking branch."
            echo "It will ask for confirmation to delete branches from each group."
            echo "While the script can live anywhere, it will work on the current working directory's Git repository."
            echo ""
            exit 0
            ;;
    esac
done

echo "Fetching and pruning..."

git fetch --prune

echo ""
echo "Branches with a \"[gone]\" upstream branch:"
echo "-----"

git for-each-ref --format '%(refname:short) %(upstream:track)' refs/heads/ | awk '$2 == "[gone]" {print $1}'
GONE=$(git for-each-ref --format '%(refname:short) %(upstream:track)' refs/heads/ | awk '$2 == "[gone]"' | wc -l)

echo ""
echo "Branches not tracking an upstream branch:"
echo "-----"

git for-each-ref --format '%(refname:short) %(upstream)' refs/heads/ | awk '$2 == "" {print $1}'
NONTRACKING=$(git for-each-ref --format '%(refname:short) %(upstream)' refs/heads/ | awk '$2 == ""' | wc -l)

echo ""

if (( $GONE )); then
read -p "Delete [gone] branches? (y/n) " REMOVE_GONE
fi

if (( $NONTRACKING )); then
read -p "Delete branches w/out tracking? (y/n) " REMOVE_LOCAL
fi

echo ""

if [ "$REMOVE_GONE" == 'y' ]; then
    git for-each-ref --format '%(refname:short) %(upstream:track)' refs/heads/ | awk '$2 == "[gone]" {print $1}' | xargs -r git branch -D
elif (( $GONE )); then
    echo "Skipping \"[gone]\" branches"
    echo ""
fi

if [ "$REMOVE_LOCAL" == 'y' ]; then
    git for-each-ref --format '%(refname:short) %(upstream)' refs/heads/ | awk '$2 == "" {print $1}' | xargs -r git branch -D
elif (( $NONTRACKING )); then
    echo "Skipping branches w/out tracking"
fi

echo ""
echo "Done."