Git - precommit and prepush hooks

Skip hooks

git commit --no-verify -m "commit message"

Sample precommit hooks

To check for code formatting using a CLI tool

For a golang app

case "$1" in
    --about )
        echo "Check go code formatting and rebuild API docs page if the spec has been updated"
        ;;
    * )
        build_api_docs

        test_fmt

        ;;
esac

To build a html documentation file based on changes to a yaml file

build_api_docs

build_api_docs() {
    if git diff --cached --name-only | grep --quiet "api_spec/api.yaml"
        then
        echo "The API spec has changed. Rebuilding the API doc page."
        npx @redocly/cli build-docs ./api_spec/api.yaml --output ./static/index.html
        git add ./static/index.html
        fi
}

To check for code formatting and import statement organizing using CLI tools

Reference: https://github.com/edsrzf/gofmt-git-hook fmt-check

#!/bin/sh

test_fmt() {
    hash gofmt 2>&- || { echo >&2 "gofmt not in PATH."; exit 1; }
    IFS='
'
    for file in `git diff --cached --name-only --diff-filter=ACM | grep '\.go$'`
    do
        output=`git cat-file -p :$file | gofmt -l 2>&1`
        if test $? -ne 0
        then
            output=`echo "$output" | sed "s,<standard input>,$file,"`
            syntaxerrors="${list}${output}\n"
        elif test -n "$output"
        then
            list="${list}${file}\n"
        fi
    done
    exitcode=0
    if test -n "$syntaxerrors"
    then
        echo >&2 "gofmt found syntax errors:"
        printf "$syntaxerrors"
        exitcode=1
    fi
    if test -n "$list"
    then
        echo >&2 "gofmt needs to format these files (run gofmt -w and git add):"
        printf "$list"
        exitcode=1
    fi
    exit $exitcode
}

test_imports_fmt() {
    hash goimports 2>&- || { echo >&2 "gofmt not in PATH."; exit 1; }

    output=`goimports -d .`
    if test -n "$output"
    then
        echo >&2 "goimports found format issues:"
        echo "$output"
        echo >&2 "Run 'goimports -w .' to fix and git add the changes"
        exit 1
    fi
}

case "$1" in
    --about )
        echo "Check Go code formatting"
        ;;
    * )
        test_fmt
        ;;

        test_imports_fmt()
esac

fmt-fix

#!/bin/sh
# NOTE: This script does not play well when adding partial changes, such as with
# git add -p or git commit -p.

test_fmt() {
    hash gofmt 2>&- || { echo >&2 "gofmt not in PATH."; exit 1; }
    IFS='
'
    exitcode=0
    for file in `git diff --cached --name-only --diff-filter=ACM | grep '\.go$'`
    do
        output=`gofmt -w "$file"`
        if test -n "$output"
        then
            # any output is a syntax error
            echo >&2 "$output"
            exitcode=1
        fi
        git add "$file"
    done
    exit $exitcode
}

case "$1" in
    --about )
        echo "Check Go code formatting"
        ;;
    * )
        test_fmt
        ;;
esac

To update package-lock.json if package.json changes

#!/usr/bin/env sh
if git diff --cached --name-only | grep --quiet "package.json"
  then
  echo "package.json has changed. Ensuring package-lock.json is up to date."
  npm install
  npm run test -- --watchAll=false
  npm run build
  git add ./package-lock.json
  fi
npx lint-staged

Sample pre-push hooks

Run tests before pushing

For a golang app

#!/bin/sh

go test ./...

For a javascript application

#!/usr/bin/env sh
npm run test -- --watchAll=false

How to format a json file before committing?

e.g. a big JSON file that is the Postman collection for the application?

It looks like there are some terminal tools. But, how do we know if all of our teammates have those terminal tools installed?

The other option is to use IntelliJ’s auto-format feature. See IntelliJ - Reformatting code before you commit it

Reading material

  1. https://github.com/edsrzf/gofmt-git-hook
  2. https://git-scm.com/book/ms/v2/Customizing-Git-Git-Hooks
  3. https://pre-commit.com/

Links to this note