git gitolite (v3) pre-receive hook for all commit messages

git, githooks, gitolite, hook

Solution

Instead of using chained update hook, I would recommend using VREFS, available with Gitolite V3. You can see all its arguments here.

Since a VREF is basically like a `git update` hook, you can, like in this script, get the log message for each commits with `git log --format=%s -1 $commit`:

Example of a script enforcing a policy on git commit messages:

#!/bin/bash

refname="$1"
oldrev="$2"
newrev="$3"
result=0

# Make sure we handle the situation when the branch does not exist yet
if ! [ "$oldrev" = "0000000000000000000000000000000000000000" ] ; then
    excludes=( ^$oldrev )
else
    excludes=( $(git for-each-ref --format '^%(refname:short)' refs/heads/) )
fi

# Get the list of incomming commits
commits=`git rev-list $newrev "${excludes[@]}"`

# For every commit in the list
for commit in $commits
do
  # check the log message for ticket number
  message=`git log --format=%s -1 $commit`
  ticket=`echo "$message" | grep -o "^[A-Z]\{2,3\}-[0-9]\+"`
  if [ "$ticket" = "" ] ; then
    echo "Commit $commit does not start with a ticket number"
    result=1
  fi
done

exit $result

cwhsu mentions in the comments:

if you're trying to write a server side hook with shell script, You probably want to take a look at "Can git `pre-receive` hooks evaluate the incoming commit?". I finally get the `oldrev`, `newrev` and `refname` by using read in shell script.

And here is also what all-zeros SHA1 means.

this line "`excludes=( ^$oldrev )`", the '`^`' simply means exclude!

Problem

I am trying to enforce a policy where each push gets rejected when even one of the commit messages does not satisfy a rule. I've distributed a hook to the devs in order for them to use it in their local repos but I also want to enforce this when they push to the origin. I have two questions: Should I use the update hook or the pre-receive hook? (I've tried to setup an update.secondary hook but it seems to me it doesn't get fired, while a pre-receive does). How can I get the message for each commit contained in the push? More specifically, I want each commit message to have a specific "valid" (for my needs) prefix. So I would like to scan for every commit in this push the commit message and validate it before I accept the push. I am using simple bash to code the hooks. Thanks!

Original source

Related problems