Git Hooks

Force developers to do stuff they would forget

Jan Olbrich
Mobile Quality
3 min readAug 10, 2017

--

When git got introduced in 2005 it changed not only the Linux community, but a lot of development processes too. Suddenly you didn't have to work in one branch anymore. Instead you would create a bunch of branches, for every feature or even change one and merge them back in later. It was so easy and fast, there was no reason anymore not to do it. Even when creating a new project Xcode will setup a git repository for you.

I remember working with Perforce and compared to git it was a huge hassle. Checking files out, so they weren't write protected anymore, checking which files changed, ignoring locally user dependent files (especially concerning the .xcodeproj files) and trying to merge a few months after creation. It didn't really help having two different development branches. As git is such a nice tool and the de-facto standard I won't go into details how to use it, but there is a nice feature not everyone knows about.

Hooks

Git has the option to add hooks to every commit. Depending on which hook you add, a different user defined script will be executed. Some of the available hooks are:

  • applypatch-msg
  • pre-applypatch
  • post-applypatch
  • pre-commit
  • prepare-commit-msg
  • commit-msg

Prepare-Commit-Msg

The prepare-commit-msg hook will execute a script, which gets the commit message passed as the first parameter $1. With this we can now change the message as much as we like. As we've talked about our conventions regarding commit messages let's check what's easy to forget, and which parts we can automate:

<TicketName> <type> : Description in present tense

Since we give our branch our tickets name, it's easy to extract:

$(git branch | grep '*' | sed 's/* //')

Furthermore we can check the type of commit by extracting the first part of our message and comparing it to the different types we have:

value=`cat $1`
type="$( cut -d ':' -f 1 <<< "$value" )"
contains=$(echo ${typeList[@]} | grep -o type | wc -w)
if [ contains -eq 0 ] then
return 1
fi

Sadly as far as I know there isn't a 100% guarantee to identify the correct tense of the description. You could try the way described here, but this is not an easy task, as natural language is quite hard.

Having these information, we can create our pre-commit-msg hook:

Pre-Commit hook

The Pre-Commit hook is able to act as a gatekeeper. It will check if everything is to our satisfaction, before we add the code to the repository. There are multiple options to check for, but we will keep it simple and check whether our code confirms to our coding conventions.

swiftlint lint --quiet

Of course we will have to add a little bit more boilerplate code, to check whether swiftlint is installed. Thus the final pre-commit hook looks like this:

Setup

There is always the problem of making sure, developer actually set up these hooks, but there is an easy solution. We've already created a setup script in an earlier post. Just create a symlink to the .git/hooks directory, make the scripts executable and you're set.

Next: Test Driven Development

Previous: Conventions

--

--

Jan Olbrich
Mobile Quality

iOS developer focused on quality and continuous delivery