Git pre-commit hooks

I'd like to introduce you to an awesome git companion : pre-commit hooks by Yelp.

Project logo

Git hooks are scripts that git executes before or after events such as: commit, push, and receive.

Git hooks are a built-in feature, but git does not offer much support for them: if there is a .git/hooks/pre-commit file, it just executes it. It's up to you to do all the wiring with existing checkers, run them consecutively and do some pretty console reporting.

Many projects exist to do this, but in my humble opinion the Yelp one is simply awesome :

  • it's really simple to install & use
  • it's written in Python
  • it already has a huge list of supported checks
  • the project is mature, has a nice & supporting community, and is open to improvements

To install it on your machine, you just need pip, Python package manager : pip install --user git+git://github.com/pre-commit/pre-commit.git@b68261c#egg=pre-commit

Then you can install Yelp pre-commit hooks into your repository: cd path/to/my/git/repo && pre-commit install. This will simply create .git/hooks/pre-commit so that it invokes the pre-commit commands.

Now all your hooks configuration fits in one file: .pre-commit-config.yaml. For example:

- repo: git://github.com/pre-commit/pre-commit-hooks
  sha: cedcea550c495d536247ca23115035b17074cac7
  hooks:
  - id: trailing-whitespace
  - id: check-json

This config tells pre-commit to use 2 predefined hooks, that check for trailing whitespaces and malformed .json files.

The checks will automagically be executed whenever you do a commit, preventing you to commit files that don't pass the checks. Here is an exemple of the resulting terminal output in case of a hook failure:

Screenshot of the tool terminal output

You can also invoke the hooks manually:

pre-commit run $hook_id # run one specific hook on all files ready to be commited
pre-commit run --files $file1 $file2 # run all hooks on some specific files
pre-commit run --all-files # run all hooks on all the files in the repo

The checks defined above live in git repositories. Many are already available for you tu use. They are associated with a sha signature, used to determine which version of the hook to use. It looks a bit verbose, but as this post explains in details, it's mandatory and you can update all your hooks to the latest version with pre-commit autoupdate.

And finally, after a small contribution from your servitor, simple hooks defined directly in the config file are now supported !

Example:

- repo: local
  hooks:
  - id: make check
    name: Run the Makefile checks
    language: system
    entry: make check
    files: ''
  - id: pyflakes
    name: Run Pyflakes
    language: system
    entry: pyflakes
    files: .py$
  - id: vnu-html-checker
    name: Download & execute VNU HTML checker
    language: script
    entry: bin/vnu_html_checker.py
    files: .html$

CommitStrip : IRL hook