Skip to content

Instantly share code, notes, and snippets.

@philiprenich
Last active February 12, 2024 23:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • 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}'
echo ""
echo "Branches not tracking an upstream branch:"
echo "-----"
git for-each-ref --format '%(refname:short) %(upstream)' refs/heads/ | awk '$2 == "" {print $1}'
echo ""
read -p "Delete [gone] branches? (y/n) " REMOVE_GONE
read -p "Delete branches w/out tracking? (y/n) " REMOVE_LOCAL
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
else
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
else
echo "Skipping branches w/out tracking"
fi
echo ""
echo "Done."
@philiprenich
Copy link
Author

This script starts by tidying up branches with a prune then finds and displays all local branches whose upstream tracking branch has been removed ([gone]) plus all local branches with no upstream at all.

You are then prompted if you would like to delete each list of branches individually. Anything by y will result in nothing happening. But answering in the affirmative with y will send the lists to git branch -D to forcibly delete (i.e., even if unmerged) those branches.

Be careful with answering "yes" to the second list as these branches only exist locally and there is no going back. If you create working branches locally without an upstream branch in your project, I recommend commenting out / removing the code that handles local branches without remotes to safeguard them.

Note: this file needs to be executable: chmod +x remove-branches.sh
It will run from the directory in which it is called.

@philiprenich
Copy link
Author

Update notes: Added a -h/--help flag with information. Clarified language. Added output when not deleting anything. Fixed bug when a blank response is sent to delete questions.

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