git delete-merged

I was pairing on a task and my colleague watched me repeatedly call the same git commands over and over in the terminal. I’d gotten into such a rhythm of calling the same sequence of commands that I hadn’t thought to codify it into one step. My colleague called me on it so now I’m writing a mini post in the hope it will force me to learn the lesson and share a helpful command.

The process I was repeating was for tidying up my local git repo when work had been merged on the remote. I was following a two step process of pruning remote branches and then removing local branches that have been merged.

The second part is more complex so let’s break that down first.

Removing local branches

We need to start by getting a list of branches that are merged:

➜ git branch --merged
* development

The output above shows that there are some branches that we probably don’t want to delete. master is our default branch so we want to keep that around and the branch marked with * is our current branch, which we also want to keep.

We can protect these two branches by filtering our list:

➜ git branch --merged | egrep --invert-match "(\*|master)"

The grep here is inverted so it will only let lines through that do not match our regular expression. In this case our regular expression matches the literal master or any line starting with an asterisk.

The final thing to do with this filtered list is to delete these branches. For this we pipe the output into git branch --delete --force:

➜ git branch --merged | egrep --invert-match "(\*|master)" | xargs git branch --delete --force

Removing references to remote branches

This is much simpler and can be achieved with:

➜ git fetch --prune

Tying the two things together we get a final command of:

➜ git fetch --prune && git branch --merged | egrep --invert-match "(\*|master)" | xargs git branch --delete --force

Giving it a name

The above is quite a long command and although you can use your command line history to find it, we can do better. I chose the name git delete-merged for my command, which can be achieved by adding an alias to my global gitconfig file:

➜ git config --global alias.delete-merged "\!sh -c 'git fetch --prune && git branch --merged | egrep --invert-match \"(\*|master)\" | xargs git branch --delete --force'"

With this in place I can now just call:

git delete-merged