Configuring Git Pre Commit Hook And TSLint (automatically)

If you’re a TypeScript user and you’re reading this, then you’re using TSLint (most likely). Recently, a situation at work arose where even though TSLint warnings were being thrown in the editor as well as terminal output, some developers (tsk tsk) were still committing these warnings.

Naturally, a pre-commit Git hook is the right candidate for this. Being able to run TSLint to ensure that before a developer can even commit let alone push, only valid code conforming to the tslint.json file can be pushed.

This poses another problem. You can’t automatically add pre-commit hooks into the repository and have everyone automatically pull them down. This is for security reasons, could you imagine if someone committed a hook that deleted a bunch of files/folders?

If you’re using a task runner like Gulp or Grunt, then you can create a clever task that copies a file to the .git/hooks directory for you.

Firstly, let’s create a pre-commit hook. In the root of your application create a new folder called hooks and a new file called pre-commit (with no file extension):

#!/bin/bash

TSLINT="$(git rev-parse --show-toplevel)/node_modules/.bin/tslint"

for file in $(git diff --cached --name-only | grep -E '\.ts$')
do
        git show ":$file" | "$TSLINT" "$file"
        if [ $? -ne 0 ]; then
                exit 1
        fi
done

Git hooks are actually bash scripts and can be quite powerful. We are creating a path to TSLint in our local application (some Git clients like Github for Windows require this) and using that to call TSLint on our files.

Secondly, let’s create our task. I personally use Gulp, but you can easily adapt the following to any task runner:

var gulp = require('gulp');

gulp.task('install-pre-commit-hook', function() {
    gulp.src('hooks/pre-commit')
        .pipe(gulp.dest('.git/hooks'));
});

gulp.task('default', ['install-pre-commit-hook']);

Running gulp or gulp install-pre-commit-hook will copy over our pre-commit hook and put it into the .git/hooks directory. It is possible on Unix based operating systems that you need to adjust the file permissions using chmod which the fs module offers a method for, but possibly not needed.

Now, throw that task into your Npm build script and anyone else who has the latest changes will get the pre-commit hook every time the task runs. No more warnings from code written by others clogging up your terminal or editor.