Testing pre-commit with git

It’s great to run tests on your code before you commit it. It’s even better to make that happen automatically!

git lets you run a script before a commit succeeds by creating what is known as a “pre-commit” hook; it’s simply an executable located at .git/hooks/pre-commit.

However, there are a few gotchas: by default, git will just run it against your current (possibly dirty) checkout. To make sure you’re actually testing the code you’re about to commit, we can stash your other changes while the tests run.

This brings up another issue: that popping a git stash that includes an index will often result in conflicts; we can solve this by using git reset --hard before we pop from the stash.

One last thing: we want to recover to the original directory state no matter what happens (e.g. maybe our test suite itself fails); so we use a bash trap to ensure that our stash popping happens no-matter the exit path.

With that all said, here is what I use as a pre-commit hook for my lua projects:

#!/bin/bash
set -eufo pipefail

if [ -n "$(git status -z)" ]; then
    git stash -q --keep-index --include-untracked
    trap "git reset -q --hard && git stash pop -q --index" EXIT
fi

echo "## Running luacheck"
luacheck .
echo

echo "## Running tests with busted"
busted
echo