Avoid pushing broken builds with a Git pre-commit hook + Gulp

(This tutorial assumes you are working on a Mac. Sorry, not sorry, Windows!)

Purpose: to prevent pushing broken tests or erroneous code that could break your remote build.

Getting Started

Git has many 'hooks' that fire when important actions occur: https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks

You can take advantage of these hooks to automate tasks when they fire. In this tutorial we will create a pre-commit hook to automatically test our code and abort the commit if anything fails, to keep you or your team from from pushing bad code.

Where to put your hook

All git repos have a .git folder (It may be hidden. See here for instructions to show hidden folders on Mac.) Git hooks are stored in .git > hooks. If the folder doesn't exist you can create it. To create your pre-commit hook you'll need to add a file named pre-commit (no file extension) to your .git > hooks folder.

Writing the pre-commit hook

Once you have the pre-commit file added to your .git > hooks folder you can add the scripts you want to run before each commit. Below is an example of a simple pre-commit hook I use.

# pre-commit

PATH=$PATH:/usr/local/bin:/usr/local/sbin

# Ensure that code that isn't part of the prospective commit isn't tested within your pre-commit script
git stash -q --keep-index

# Test prospective commit
gulp test
RESULT=$?

git stash pop -q

[ $RESULT -ne 0 ] && exit 1
exit 0

The first line is just a comment with the filename.

PATH=$PATH:/usr/local/bin:/usr/local/sbin is something you have to add to get your gulp commands to work. Without it, you'll get the error gulp: command not found.

git stash -q --keep-index is a line I took from this guy. It stashes files in your working copy so they don't interfere with linting or testing the files in your commit. Pretty neat!

gulp test, obviously, runs your gulp tests. RESULT=$? sets the exit status of the test to a variable.

git stash pop -q releases your stashed files after the gulp test runs.

[ $RESULT -ne 0 ] && exit 1 checks the exit status stored in the RESULT variable. If it is not equal to 0, it exits with a status of 1 which aborts the commit. Otherwise exit 0 allows the commit to complete successfully.

Testing

In order for this hook to run, you must make the file executable. Use the following command in your .git > hooks directory to do so:

sudo chmod +x pre-commit  

(Just remember, you should always be carful when using sudo.)

Now that your file is executable, you can test it by purposely breaking one of your unit tests!

Congrats!

Now, you're all set save yourself the embarrassment of pushing bad code and breaking your project build! Keep in mind, the .git folder doesn't get pushed to your project repository so the rest of your team won't be able to use your pre-commit hook unless they too manually install it.

In an upcoming post, I'll go through how you can automate the installation of your pre-commit hook so your whole team is forced to use it. :D


Questions? Additonal tips? Please share your thoughts in a comment below!