Last Updated: February 25, 2016
·
17.84K
· ashiguruma

Automatically adding Git pre-commit linting with Grunt

Using the Git pre-commit hook along with Grunt.js allows you to perform linting on your code before it is committed. This can help your team stick to a particular coding style.

It's worth reading up on Git commit hooks and Grunt.js if you haven't already.

A pre-commit hook normally has to be manually copied/written in to .git/hooks on developers' machines. Instead Grunt with a little help from npm can help automate the process.

Your lint pre-commit hook would look something like this

#!/bin/sh
#
# Pre-commit hooks

# Lint stuff before committing
grunt jshint

You'll need to npm install grunt-contrib-clean and grunt-shell. The following Grunt tasks will remove the current pre-commit hook executable (if there is one) then copy the pre-commit executable from the project in to .git/hooks.

// Clean stuff up
clean: {
  // Clean any pre-commit hooks in .git/hooks directory
  hooks: ['.git/hooks/pre-commit']
},

// Run shell commands
shell: {
  hooks: {
    // Copy the project's pre-commit hook into .git/hooks
    command: 'cp git-hooks/pre-commit .git/hooks/'
  }
}

You'll need to include the tasks and then they can be tied up with a single task, in this case called hookmeup.

grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-shell');

// Clean the .git/hooks/pre-commit file then copy in the latest version
grunt.registerTask('hookmeup', ['clean:hooks', 'shell:hooks']);

You can now run grunt hookmeup and the pre-commit hook will be copied to your .git/hooks directory.

Lastly you can automate this by running grunt hookmeup when an npm install is completed, using a postinstall script in your package.json file.

"scripts": {
    "postinstall": "grunt hookmeup"
}

When you or another developer on your project runs npm install the pre-commit hook will be added to the .git/hooks directory. When you git commit your code will be linter. Should the linting fail the commit will fail too.

The same setup can also be used to run tests, concatenation, minifying etc. Nathan LaFreniere's precommit-hook npm module provides nice set up for linting and testing with the pre-commit Git hook.

Thanks to codeinthhole and Andreas Köberle for providing great articles on how to work with Git hooks.

6 Responses
Add your response

Hi, I think the link to Nathan's precommit npm module should be https://github.com/nlf/precommit-hook

over 1 year ago ·

Thanks for letting me know. I think the author has updated their account name. I've changed it now.

over 1 year ago ·

Awesome! FYI You can get rid of grunt-shell by using grunt-githooks: https://github.com/rhumaric/grunt-githooks

Made it a bit cleaner

over 1 year ago ·

This is great, thanks for sharing.

Was wondering, have you done much in the way of callbacks? For example, how to stop the commit if the jslint fails? Or, if I want to run a build script to minify scripts, how to wait for it to be done?

over 1 year ago ·

I used copy instead of shell:

copy: {
githooks: {
files: [{
flatten: true,
src: ['git-hooks/pre-commit'],
dest: '.git/hooks/pre-commit'
}]
}
}

over 1 year ago ·