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
      origin/feature/some-feature
      origin/feature/another-one
    

    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
    deleted=$localBranches
    for branch in ${remoteBranches[@]}; do
        deleted=$(sed "s!${branch}!!" <<< ${deleted})
    done
    
  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:

#!/bin/bash

prefix="feature/richmond/"
# only delete my own branches

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

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

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

if [ "$deleted" == "" ]; then
	echo "Nothing to delete, you local is clean."
else
	git branch -dl ${deleted}
fi
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.