Global PEP8 Git pre-commit check hook

If someone did a quick study to see how many Git commits were for forgetting to check PEP8 compliance before pushing, I bet it would be on the order of 3% as an initial guess. This clutter can be eliminated by making a simple Git pre-commit hook that applies to all repositories. For non-Python repositories, the flake8 command will quickly exit as it doesn’t find any .py files.

This example makes the following assumptions:

  • flake8 is installed and working e.g. pip install flake8
  • All the Python projects have the file setup.py at the top-level (to avoid running flake8 on large non-Python projects)

Procedure

This procedure is for both Unix-like systems and native Windows.

  1. Create a directory to hold the Git hooks:

    mkdir -p ~/.git/hooks
    • Windows:

      mkdir %HOMEPATH%\.git\hooks
  2. Tell Git this is a directory for Git hooks:

    git config --global core.hooksPath ~/.git/hooks
    • Windows:

      git config --global core.hooksPath %HOMEPATH%\.git\hooks
  3. Create executable file under user home directory .git/hooks/pre-commit containing the following. Notice the first shebang first tries to use Unix-like Bash, and falls back on Windows to Git’s built-in Bash.

    #!/bin/bash; C:/Program\ Files/Git/user/bin/sh.exe
    
    export pyfiles=$(git diff --staged --name-only | grep -E "\.py$")
    
    if [[ ! -z $pyfiles ]]
    then
    grep -l 'breakpoint' $pyfiles && { echo "remove breakpoint before commit"; exit 1; }
    
    exec flake8 $pyfiles
    fi
    
    exec git diff-index --check --cached HEAD --

This global pre-commit check hook does three things:

  1. get a list of Python file names that changed.
  2. check PEP8 and that Python ≥ 3.7 breakpoint debug statements are not present.
  3. Checks for trailing whitespaces in any code language.

Bypass checks

These checks can be bypassed at any time for a commit by:

git commit --no-verify

References

https://gist.github.com/arturadib/97a17752301ee796f9a0