#!/bin/sh # # Copy or link this file as ".git/hooks/pre-commit". # Prepare a copy of the message: # - strip comment lines # - stop at "diff --git" (git commit -v) commit_msg="$GIT_DIR/COMMIT_MSG" sed -n -e '/^#/d' -e '/^diff --git/q' -e 'p;d' "$1" > "$commit_msg" die() { echo 'commit-msg hook failure' 1>&2 echo '-----------------------' 1>&2 echo '' 1>&2 echo "$@" 1>&2 echo 'To continue editing, run the command git commit -e -F '"$commit_msg"' (assuming your working directory is at the top).' 1>&2 exit 1 } #----------------------------------------------------------------------------- # Check the commit message layout with a simple state machine. msg_first() { len=$(echo -n "$line" | wc -c) if test $len -eq 0; then # not yet first line return elif test $len -lt 8; then die 'The first line must be at least 8 characters: -------- '"$line"' -------- ' elif test $len -gt 78; then die 'The first line may be at most 78 characters: ------------------------------------------------------------------------------ '"$line"' ------------------------------------------------------------------------------ ' elif echo "$line" | grep "^[ ]\|[ ]$" >/dev/null 2>&1; then die 'The first line may not have leading or trailing space: ['"$line"'] ' else # first line okay state=second fi } msg_second() { if test "x$line" != "x"; then die 'The second line must be empty: '"$line" else state=rest fi } msg_rest() { false } # Pipe commit message into the state machine. state=first cat "$commit_msg" | while IFS='' read line; do msg_$state || break done && rm -f "$commit_msg"