How to easily prune your local branches without a remote using Git
Consider the following, not so exciting, git workflow, common in trunk-based development, where branches should be short-lived.
You start by cloning an existing repository...
$ git clone https://github.com/matthiasguentert/flux-minikube.git
You create a new local branch, make changes, and commit them...
$ git switch -c feat/the-next-big-thing
...
$ git add .
$ git commit -m "implements the next big thing"
[feat/the-next-big-thing 914d7be] implements the next big thing
1 file changed, 1 insertion(+)
create mode 100644 TheNextBigThing.cs
You push the branch back to the remote...
$ git remote -v
origin git@github.com:matthiasguentert/my-project.git (fetch)
origin git@github.com:matthiasguentert/my-project.git (push)
$ git push --set-upstream origin feat/the-next-big-thing
At this point, the local branch has a remote tracking branch.
push.autosetupremote=true
in your git config, so you don't have to set the upstream manually. `git config --global --add --bool push.autoSetupRemote true`
You create a pull request that gets approved, and the remote branch gets deleted. You switch back to main, pull in the latest changes, and head to the next task.
$ git switch main
$ git pull
$ git switch -c feat/another-task
...
Over time, your list of local branches without a remote tracking branch accumulates. Sure, you can periodically review your list of local branches and perform some manual cleanup...
$ git branch -va
feat/feature1 9f9ccc9 [origin/feat/feature1: gone] a commit msg here
feat/feature2 abcdeaf [origin/feat/feature2: gone] a commit msg and here
feat/featureN 1234567 [origin/feat/featureN: gone] a commit msg there
$ git branch -d feat/feature1
$ git branch -d ...
But this is tiring and repetitive...
The shortcut
So, long story short. I use two one-liners with aliases to save me some time every day.
# git list untracked branches
alias glu="git fetch -p; git branch -vva | grep ": gone\]" | awk '{print \$1}'"
# git remove untracked branches
alias gru="git fetch -p; git branch -vva | grep ": gone\]" | awk '{print \$1}' | xargs git branch -D"
This should work in Bash and Zsh. So add the alias either to ~/.zprofile
when on Mac or your ~/.bashrc
.
In case you are not using squash commit on merge, you should replace git branch -D
with git branch -d
.