Git Flow – Cleaning your Local Branches

Git Flow indeed is the one of the most popular Git Branching Model/ Strategy/Workflow in use today.
You can read more about Git Flow from the creator himself’s post, “A successful Git branching model“.

Git Flow is very helpful for quite matured projects (traditional) rather than the infant ones (fast-phased or continuous), IMHO. And for the matured ones, Git Flow has been proven to work very well.

The strategy’s flow is a little slow-phased on the part of releasing branches (features) into master/production. And when a project hits a lot of feature tickets/requests the repository tends to clog up, local and remote. And when those branches are merged and closed from the origin, you will encounter the frustration of trying to remove those humongous number of merged branches from your local repository. And Git does not have, yet, the single command we want to delete all of those at the same time. Now, many of us searched the internet for answers, including myself, and got disappointed. 🙁

My answer? I created a script to do just that. 🙂

Steps how I came up with the Script

  1. Since git does not have a command to print us all the deleted branches, I tried to go backwards by printing all remote branches; and local branches, and then loop on the list of remote branches and delete them from the list of local branches.
    To get the remote branches, use

    $ git branch -r --no-merged

    This would print something like,

    $ git branch -r --no-merged

    Now, I only want the branch name so I can easily strip my local branches list with it, and create a list (array) of it.  I used this piped command.

    IFS=" " read -r -a remoteBranches <<< $(git branch -r --no-merged | sed 's/\// /' | awk '{print $2;}' | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g')
  2. Create a list/array (space-delimited string) of local branches.
    localBranches=$(git branch | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n  / /g')
    # this command: sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g'
    # strips all the newline and the 2 spaces before each line of the git branch result
  3. One by one strip the branches in remoteBranchesfrom the localBranches
    # loop and delete one by one
    for branch in ${remoteBranches[@]}; do
        deleted=$(sed "s!${branch}!!" <<< ${deleted})
  4. And now delete the local branches. From what’s left of your local branches list after stripping all branches from remote, those branches are already “not existing” on your remote.
    git branch -dl ${deleted}

To sum it all up, here is the complete script:


# only delete my own branches

if [ "$1" != "" ]; then
	# or specify a prefix as argument

currentBranch=$(git branch | grep "*" | awk '{print $2;}')
git checkout master

IFS=" " read -r -a branches <<< $(git branch -r --no-merged | grep ${prefix} | sed 's/\// /' | awk '{print $2;}' | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g')
# get all existing branches in remote

localBranches=$(git branch | grep ${prefix} | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n  / /g')
# get all local branches

for branch in ${branches[@]}; do
	# loop and delete one by one
    deleted=$(sed "s!${branch}!!" <<< ${deleted})

if [ "$deleted" == "" ]; then
	echo "Nothing to delete, you local is clean."
	git branch -dl ${deleted}
git checkout $currentBranch
# checkout where you last checked out

Or you can also checkout the Gist i created.

I added a prefix as I only want my branches to be deleted from my local.
This script is working with git version ~1.7

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload CAPTCHA.