Home

Awesome

Want consistent code in your team...?

Learn how to use Pre-Commit Today

Pre-commit hooks let you run checks before allowing a commit (e.g. JSLint or Test Coverage).

Checklist

Think of pre-commit as an automatic checklist for your code. The checks prevent people from committing code that does not meet the required standards, saving everyone time. Imagine never having to read sloppy code again...!

What are Git Hooks?

Git Hooks are a a way to fire off custom scripts when certain important actions occur. e.g: commit, push, and merge. There are two groups of these hooks: client side and server side. The client-side hooks are for client operations such as committing and merging. The server-side hooks are for Git server operations such as automatically starting the build/test server or notifying team-mates of changes.

You can use these hooks for all sorts of reasons, but here we are going to focus on client-side pre-commit hooks (checks that are run before code is allowed to be committed).

What types of checks can we run?

How ?

Node.js

In node-land there are two popular modules we can use to run pre-commit checks:

Both are functionally equivalent so take your pick.
I'm covering pre-commit because it has more concise documentation.

Install

Install the node module and save it as a development dependency for your project:

npm install pre-commit --save-dev

Define the Scripts we want to Run

Example package.json file:

{
  "name": "learn-pre-commit",
  "version": "1.0.0",
  "description": "Node.js pre-commit tutorial",
  "repository": {
    "type": "git",
    "url": "https://github.com/nelsonic/learn-pre-commit"
  },
  "devDependencies": {
    "istanbul": "^0.3.2",
    "pre-commit": "0.0.9",
    "tape": "^3.0.1"
  },
  "scripts": {
    "test": "tape ./test/*.js",
    "coverage": "istanbul cover tape ./test/*.js && istanbul check-coverage --statements 100 --functions 100 --lines 100 --branches 100",
    "jshint": "jshint -c .jshintrc --exclude-path .gitignore .",
  },
  "pre-commit": [
    "jshint",
    "coverage"
  ]
}

Explanation

The interesting bits here are:

a) scripts - a list of tasks that can be run. Each script can be run by issuing the command: npm run script-name (e.g: npm run coverage to check the test coverage).

b) pre-commit - an array of the scripts we want to run (in order) before we allow a commit. In this case jshint ensures our code is consistent according to the rules for the project and coverage ensures that our desired level of code/test coverage (100%) is met.

Example

See /example for a Hello World example.

Build Status Coverage Status Code Climate Dependencies devDependency Status

Try it in your own projects! If you have any questions, submit an issue on GitHub or tweet me @nelsonic

Elixir/Phoenix

As Phoenix comes with Node.js as standard, we can take advantage of this and use the same method as above. The only difference is the script we use to run our tests/coverage:

  ...
  "scripts": {
    "coverage": "mix coveralls"
  },
  "pre-commit": [
    "coverage"
  ]
}

Advanced How?

Problems in Node Land

While using pre-commit, we found this issue.

On installation pre-commit uses symlink to copy a pre-commit hook into your .git/hooks folder. Symlink is useful as it allows you to repeatedly change your hook script without having to copy it into your private .git/ folder.

This script will then use the package.json to find other scripts to call. But this sometimes causes a problem as in some cases Windows' default security policy will only allow administrators to create symbolic links. Solution...

Do it yourself!

If you inspect the .git/hooks folder you will find you can add/remove hooks easily.

Hooks can be written in most scripting languages so you can find some online to use or write your own with your favourite language.

Modify your hooks directly by copy and pasting manually or with a script. The latter is better as it enables all developers in a team to do so easily, but...

You will need to find a mechanism to make sure developers first install them and second keep them up to date.

An example of custom hooks written with node and a script to copy them into .git folder can be found here.

Would it have been easier to just adjust the security policy? Probably, but it turns out writing git hooks is easy too! See below for more information on types of hooks.

Background Reading

Git Hooks

Code Style

Code Quality

Java, Ruby, Python, etc.

If you don't want to write your own pre-commit hooks:

If you find better pre-commit tools for any language, please inform me or send a PR!