With git remote prune origin
I can remove the local branches that are not on the remote any more.
But I also want to remove local branches that were created from those remote branches (a check if they are unmerged would be nice).
How can I do this?
After pruning, you can get the list of remote branches with git branch -r
. The list of branches with their remote tracking branch can be retrieved with git branch -vv
. So using these two lists you can find the remote tracking branches that are not in the list of remotes.
This line should do the trick (requires bash
or zsh
, won't work with standard Bourne shell):
git fetch -p ; git branch -r | awk '{print $1}' | egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) | awk '{print $1}' | xargs git branch -d
This string gets the list of remote branches and passes it into egrep
through the standard input. And filters the branches that have a remote tracking branch (using git branch -vv
and filtering for those that have origin
) then getting the first column of that output which will be the branch name. Finally passing all the branch names into the delete branch command.
Since it is using the -d
option, it will not delete branches that have not been merged into the branch that you are on when you run this command.
If you would like to have this as an alias, add these lines to your .bashrc
file:
alias git-list-untracked='git fetch --prune && git branch -r | awk "{print \$1}" | egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) | awk "{print \$1}"'
alias git-remove-untracked='git fetch --prune && git branch -r | awk "{print \$1}" | egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) | awk "{print \$1}" | xargs git branch -d'
Then, the procedure for pruning becomes:
git remote prune --dry-run origin
git remote prune origin # Removes origin/asdf that's no longer on origin
git-list-untracked
git-remove-untracked # removes asdf [origin/asdf] where [origin/asdf] no longer exists (after previous command)
If you use squash merges, replace -d
with -D
. But note that this means that git is not checking whether the branch has been merged before deleting it.