Delete Git Branches with No Remote Tracking Branch

Do you like to frequently remove local Git branches that no longer have a remote/upstream tracking branch, but hate having to manually go through your branches to individually delete them? Same. I wrote a Bash script to automatically find and delete these leftover branches.

While the above link will be the canonical version of the script, I'll post it here too so we can easily go over it together.


echo "Fetching and pruning..."

git fetch --prune

echo "Gone branches:"
echo "-----"

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

echo ""
echo "Branches without upstream:"
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 remote? (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

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

echo ""
echo "Done."

This is a Bash script and I wrote it to work on my Mac. I believe with Windows Subsystem for Linux, Windows users will be fine.

Save this into a .sh file and set it to be executable (Mac/Linux: chmod +x You can save it outside of the repository and it will run in whatever directory you call it from: /work/project-x/dev $ ../ for example.

To start, we fetch to update our branches list and prune references to remote branches that no longer exist. Next list all branches that used to have a remote branch, but no longer do. Follow this by branches that have never had an upstream branch set.

Both those lists are displayed as output in the terminal and we are prompted once for each list if we'd like to delete the displayed branches (Anything but an affirmative y results in nothing happening).

It's important to note that branches that have never had a remote don't exist on the remote repository and you may not want to delete these! Use this option with caution, these branches only exist in the local repository and will be removed permanently. If your workflow allows for locally created branches, you may want to just remove the parts of this script that can delete those.

Some workflows have all branches created on the remote first (e.g., through the Pull Request interface) so any local-only branches can probably safely deleted. That's the case with one of my projects which is why I added this, but kept it as a separate list and prompt.

Hopefully this is a useful little tool that will save you some time!