Delete All Local Git Branches Except for master or main

Hero image for Delete All Local Git Branches Except for master or main. Image by John Barkiple.
Hero image for 'Delete All Local Git Branches Except for master or main.' Image by John Barkiple.

Have you ever found yourself drowning in a sea of old feature branches whilst working with Git? Whether it's local or remote branches that are cluttering up your workspace, sometimes a little cleanup is necessary. If you're looking to tidy up by deleting all branches except the master (or main), here's a couple of oneliners that I use...


Why Delete Branches?

First off, why even bother deleting branches? I tend to find that after a while, my local repository becomes a huge list of feature branches, bugfixes, tweaks and changes. Particularly as you draw towards the close of a project and really you are only dealing with very minor changes on each branch (but on a lot of them), it can get really unwieldy. They have all longsince been merged into production and forgotten about anyway.

So, having a good cleanout every now and again keeps things manageable. It helps in avoiding confusion over which branches are active or outdated, and makes it easier to find what you need, when you need it.


Deleting Local Branches

So, starting with local branches. Before you begin, ensure you've merged anything that you want to keep into the master or main branch. Then, if you're in a position where you just want to get rid of everything locally except for your master or main branch, here's a quick command:

git branch | grep -v "master\|main" | xargs git branch -d

Note: The command above uses master\|main to ensure that neither your master branch nor your main branch are deleted, covering both naming conventions.

In this command, we're essentially listing all branches, filtering out the master or main branches, and then deleting the rest. It's simple and effective!

I should point out a minor caveat, however: grep v 'master' will filter out any branch with 'master' in its name. This means it doesn't just exclude the exact branch named 'master', but also any branch names that include 'master' as part of their name, like 'fix/brokenmaster' or 'masterprod'. So, these would be excluded from the deletion list too.

You can modify the command I've shared above to use a regular expression instead of simply stringmatching:

git branch | grep -vE "^(master|main)$" | xargs git branch -d

Now, we use grep E (extended regex) with ^(master|main)$. The ^ denotes the start of the line, the $ denotes the end, and the pipe | acts as an 'OR' operator. This ensures that only lines exactly matching 'master' or 'main' are filtered out. Be really careful, though; we'll come back to that in a moment...

The difference between d and D

For the sake of a little extra security, in the commands above, I've included the use of d (in lowercase) for deletion. If you use those commands, you may find that some branches aren't deleted, and you instead get presented with messages that look like this:

error: The branch 'feat/interstitial-messaging' is not fully merged.If you are sure you want to delete it, run 'git branch -D feat/interstitial-messaging'.

Allow me to explain. In Git, when we're deleting branches, using d to delete a branch is the 'safe' option; it only deletes a branch if it has been fully merged. If the branch has not been fully merged (or I've sometimes found you've merged it into master via squash), Git will refuse to delete the branch and show you that message instead to prevent potentially losing any data.

If you're absolutely sure that you want to delete it, you can use D instead. This option forcefully deletes a branch regardless of whether it has been merged or not. As you might appreciate, a mistake here could lead to you permanently losing your code if it hasn't been integrated somewhere else.

So, if you are absolutely and positively sure that you want to delete all your local branches (except for master or main), then you just need to adjust that first example to replace d with D, like so:

git branch | grep -v "master\|main" | xargs git branch -D

What About Deleting Remote Branches?

Generally, I would advocate against using copyandpaste commands that you've found on the internet to delete in your remote repository source. In my mind, it makes much more sense to spend time in your Git UI on GitHub (or wherever) manually going through each branch.

Nevertheless, it would be a halfcomplete article if I didn't include the howto of deleting feature branches from remote.

So firstly, we need to fetch the latest updates from your remote:

git fetch -p

We use the p or prune flag here to get rid of any remotetracking references that no longer exist on the remote.

Now, for the actual deletin':

git branch -r | grep -v "master\|main" | sed 's/origin\///' | xargs -I {} git push origin --delete {}

Here, what we're doing it listing all remote branches, we then exclude master and/or main, format the branch names, and then push the delete command to the remote repository for each.


A Word of Caution

I already mentioned above how dangerous it can be to simply copy and paste code that you've found on a random website into your terminal. Hopefully, there's enough information about me floating around for you to feel relatively safe in what I'm sharing with you, but please always do your own research.

Deleting branches cannot be undone (although I have been known to use Time Machine backups in the past in a semifutile attempt to do just that). Always doublecheck the branches you're about to delete. Be absolutely sure that there's nothing still in those branches that you want before you hit the enter key.


Categories:

  1. Git
  2. Guides