Git cleaning or: How I Learned to Stop Worrying and Love commit hooks

By EGO Angel April 11, 2019No Comments
Git: removing of old branches

Today, I want to show how you can automate removing of old branches when merging child branches in a parent branch. Now, one can say this topic had already been overtaken due to the wide use of CI and services like github/bitbucket. But as the story says: “Github will help only those who help themselves.”

Let’s assume we have a project of the following structure:

Project structure

To start removing branches, we need to define first what actually needs to be removed.

git branch --merged

Returns all branches names that contain current commit. If HEAD is on e, we will get the following output:

* master

To exclude the current branch, as well as a master one, from the output, let’s add the following regex:

git branch --merged | egrep -v "(^\*|master)"

If you need to exclude any more branches, ‘develop’ for example, the expression will look like:

git branch --merged | egrep -v "(^\*|master|develop)"

To remove detected branches from the remote repository, we run the command:

git push --delete origin my_branch_name

And here’s how it will look like after being combined with the logic we already have:

git branch --merged | egrep -v "(^\*|master)" | xargs -n 1 git push --delete origin

Now after we’ve written a code that removes a branch from a remote repository, we need to make sure that local branch copies always end up being removed too. The following instruction will help us so this:

git fetch -p && git branch -vv

After removing all branches from a ‘remote’, this is how instruction’s output will look like:

  feature/Branch1 c220b82 [origin/feature/Branch1: gone] Feature 1
  feature/Branch2 91141c1 [origin/feature/Branch2: gone] Feature 2
  feature/Branch3 3c444ba [origin/feature/Branch3: gone] Feature 3
* master      	ddbd1ab [origin/master]

As seen from the output, branches now have ‘gone’ status, which allows us to write a regex, find branches, and delete them.

git fetch -p && git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -d

From combining it with the previous expression, we’ll get:

git branch --merged | egrep -v "(^\*|master)" | xargs -n 1 git push --delete origin | git fetch -p && git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -d

After command execution, we’ll get the following output:

 - [deleted]     	feature/Branch1
 - [deleted]     	feature/Branch2
 - [deleted]     	feature/Branch3
Deleted branch feature/Branch1 (was c220b82).
Deleted branch feature/Branch2 (was 91141c1).
Deleted branch feature/Branch3 (was 3c444ba).

For the sake of convenience, let’s add ‘alias’ for this command into gitconfig, by calling

git config -e --global

And adding the following string there:

    clean-branches = "!git branch --merged | egrep -v '(^\\*|master)' | xargs -n 1 git push --delete origin | git fetch -p && git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -d"

Now we can remove branches with a single command

git clean-branches

There’s only one small problem left: no to forget to run a script that removes unnecessary branches whenever merging is done. But wait, is it a problem at all? We could just use ‘post-merge commit hook’, and that’s it!

To do this, let’s create a .git/hooks/post-merge file, and add one single command to it:

git clean-branches

Let’s make sure that file is accessible:

chmod +x .git/hooks/post-merge

So now, after every merge, all merged branches will be removed automatically.

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
this post was shared 0 times

Leave a Reply

Your email address will not be published.