Skip to content

Instantly share code, notes, and snippets.

@philiprenich
Last active March 24, 2025 13:55
Show Gist options
  • Save philiprenich/b62cb7f68c2fd4a966a9eaade1c1ef48 to your computer and use it in GitHub Desktop.
Save philiprenich/b62cb7f68c2fd4a966a9eaade1c1ef48 to your computer and use it in GitHub Desktop.
Script to remove git branches without an upstream (removed or non-existant). Corresponding blog post: https://www.philiprenich.com/blog/delete-git-branches-with-no-remote-tracking-branch/
#!/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."
@philiprenich
Copy link
Author

Update notes: improved output verbosity based on data

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment