Power of Eloquence

When saying “Hello World!” isn’t enough anymore

Git Commands for Maintaining Health Status of Your Code Repository System

| Comments

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:

Show branched that have been merged to master
1
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

Delete the branches that have been merged to master
1
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:

Delete the branches that have been merged to master (not including master itself!!)
1
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.

Delete the branches remmotely that have been merged to master (not including master itself!!)
1
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:

Their aliases equivalent
1
2
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!

Comments