Deleting irrelevant local git branches

At work today, I was writing some code, when I went to checkout another branch that I was working on. I forgot the name of it, and I didn’t have gitlab open in another tab to find the name (which is odd for me), so I did something seemingly normal: git branch to see the list of all of my branches.. I was bombarded with branches. Turns out, I hadn’t cleaned my local in a long time. I thought “oh, I’ll just delete everything that doesn’t have an upstream anymore, and clean this up.” Well, there’s no git command for that!

So, a bit of googling #

I found a bunch of solutions on several sites, but the best (I think) is a combination of a few:

git checkout master

git branch -vv | grep ': gone]' | awk '{print $1}' | xargs git branch -d

Now, before I run anything, I look into what it all means if I don’t already know. Note that this will destructively remove all of those branches that had, but no longer have an upstream. Here’s a quick rundown of all the pieces for the curious souls.

git branch -vv #

This is similar to git branch, but it lists more information about all of the branches on your local:

$ git branch -vv

* master    4635459 [origin/master]          Made pages on mobile
  feature-a b33fabc [origin/feature-a: gone] Created a thing
  feature-b abcb33f [origin/feature-b: gone] Did something
  feature-c 1234abc Created another thing

The branches that have an upstream include the name of that upstream in square braces [], and the branches that had an upstream that no longer exists include the name of that previous upstream with the addition of : gone in the braces. We can use this to our advantage.

grep ‘: gone]’ #

Hopefully, this is pretty straightforward – grep is used to search/filter text. In this case, each input line is a branch that we have on local (and its upstream counterpart). The ones that don’t exist on upstream anymore will include that : gone] substring. Our results from here look like:

  feature-a b33fabc [origin/feature-a: gone] Created a thing
  feature-b abcb33f [origin/feature-b: gone] Did something

So we’ve filtered this list down to just the relevant branches, but now we need to get this data into a shape that we can use it.

awk ‘{print $1}’ #

This is the fun one. I have a post coming soon just about Awk. In short, this separates the input lines on whitespace characters, and grabs the first (1-indexed) per line, and converts the output to just that. By now, our results look like:


xargs git branch -d #

Xargs is another great one. Basically, it executes the command you give it, with each space-separated (including newline) item fed into it as the arguments for a separate execution of that command. It will execute, based on the arguments given to it:

git branch -d feature-a
git branch -d feature-b

And this does the behavior we wanted. Success!

Extra notes #

Using git branch -d deletes a branch only if it has been merged into its upstream branch. If a branch hasn’t been merged into its upstream, it’ll just throw a warning and skip it. This can happen if you had local changes, then the upstream branch was deleted before you ever pushed those changes. Often times, you want to delete these local branches too (after all, this is a clean-up script!), and that can be done by slightly modifying our above command to use git branch -D instead, which will force delete the branches given to it.

Hopefully this was helpful to anyone who needs to clean up their local. Maybe you also learned a trick or two about some unix commands. If you’re interested in this stuff, keep an eye out for my post about awk that’ll be coming soon :)


Now read this

Structuring your Go web application

I was working on the Blog Engine (Bla) as one of my first big projects written in Go. I did a bit of planning, then started organizing code into a way that I felt made sense. It quickly fell into chaos, since I was using certain OO... Continue →