At some point, when working with your feature branches, you need to do some bit of ‘trimming’ with your stale branches that you no longer need to keep.
These stale branches include:
- branches have been merged to the master branch, both locally and remotely.
- branches that were no longer required as actual features by the client.
- branches that were built for prototype or demo purposes.
With those in mind, these will build up over time thus we need to periodically remove them as needed before we start working on other new feature branches.
When finding out which branches have been merged to the master, you run the following:
git branch --merged master
So we know which branches can we safely remove them on our local machine, thus you would think we should perform git branch -d *branch_to_delete*
right?
Which is fine, if you have a few branches to deal with. But what if, you have more than 10, 15, 20 or even over 100 to deal with? Wouldn’t that take forever to complete such simple trimming operation? You wouldn’t think it’s worth such menial effort to do so we need to automate this.
By tweaking in our previous commands, we do this instead
git branch --merged master | xargs git branch -d
This piping command line is pretty neat! What this is saying is as we list out all branches merged to master to be outputted to a usually terminal screen, they will be served as input parameters for our next CLI command to absorb and execute by using the pipe |
operator, followed by xargs
command. xargs
is a Unix utility belt to accept standard inputs for any command we like to execute next in our piping chain. As for this case, we’re effectively doing git branch -d **branch_name**
without having to type out branch_name
every single time. xargs
takes care of branch_name
input parameter for us as long as the preceding command git branch --merged master
does not run into any problems fetching valid parameters.
And that’s it!
But there’s only little catch here - the above command not only delete the merged branches (as we originally prescribed it), but we’re also deleting the main master branch as well if we run this. Why would it do such careless thing like that?
If you look carefully at this command line:
git branch --merged master
This would also output master
branch, along with other feature branches locally. As master
branch usually (and always) get merged at some constant basis by you or your team members, thus it satisfies the above condition and it will get used as an input param for your xargs
to perform the next thing - which is to delete master
branch in this case.
Which is not we want!
Thus to prevent this, we write our safeguard code to do the following:
git branch --merged master | grep -v 'master$' | xargs git branch -d
We place grep
command into the pipeline chain between xargs
and git branch --merged master
pieces. What this one does is to filter out any inputs that match master$
keyword using v
flag option. Thus you will expect is that master
is not amongst the list of merged branches to be earmarked for deletion.
There you have it!
This is how you want to maintain your local branches for your git repository.
That’s on one side of the fence.
On the other side of the fence, you also need to deal with the remote repository as well.
The command line is to perform such operation would look like this.
git branch -r --merged master | sed 's/ *origin \///' | grep -v 'master$' | cut -d/ -f2- | xargs -n 1 git push --delete origin
This is more or less the same with previous local branch deletion operation, but it’s a little more involved - which I’ll explain a bit.
The clause here
sed 's/ *origin \///' | grep -v 'master$' | cut -d/ -f2-
This is saying we want our matches to, not only ignore any remote repo suffix that ends with master
, but also specifically fit any remote branches that have origin
prefixes, as most git-based repository system uses origin
as the default remote repository end-point. Once those matching conditions are satisfied for branch name searches we want, we then remove origin from the branch name before it gets piped for deletion.
That’s it!
Bear in mind - if you work in a sizeable team where you have more than just one main branch such as eg develop
, then you may want to tweak grep
and sed
commands to accommodate for extra key branches you want to keep before getting things purged.
Finally, once you’re done and contented with the above setup, you can then create bash aliases for these like so:
alias gitdlb="git branch --merged master | grep -v 'master$' | xargs git branch -d"
alias gitdrb="git branch -r --merged master | sed 's/ *origin \///' | grep -v 'master$' | cut -d/ -f2- | xargs -n 1 git push --delete origin"
Hope you’ve learned something useful to automate little useful things like this on a day to day basis.
Till next time - Happy Coding!