Remove all branches without an upstream

Oct 20, 2023

Oftentimes I create branches or worktrees and they don't end up getting pushed to remote and I forget about them. Alternatively, they do get pushed and I forget to prune them. Here's how to list them, and optionally to remove them.

List all branches whose upstream has been removed

git branch --format="%(refname:short) %(upstream:track)" | 
    grep "\[gone\]"

upstream additionally respects :track to show [ahead N, behind M]... prints [gone] whenever unknown upstream ref is encountered.

$ git branch --format="%(refname:short) %(upstream:track)" | 
    grep "\[gone\]"
TheZoc/master [gone]
git config --global alias.gone '!git branch --format="%(refname:short) %(upstream:track)" | grep "\[gone\]"'

Remove all branches whose upstream has been removed

To remove them, pull out the branch name and use xargs to remove the branches:

git branch --format="%(refname:short) %(upstream:track)" | 
    grep "\[gone\]" |
    cut -f1 -d " " |
    xargs -I{} git branch -D {}

for example:

$ git branch --format="%(refname:short) %(upstream:track)" | 
    grep "\[gone\]" | 
    cut -f1 -d " " |
    xargs -I{} git branch -D {}
Deleted branch TheZoc/master (was 3d7b0ae).

You might alias this one to git rm-gone:

git config --global alias.rm-gone '!git branch --format="%(refname:short) %(upstream:track)" | grep "\[gone\]" | cut -f1 -d " " | xargs -I{} git branch -D {}'
↑ up