4

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:

  1. 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).

  2. 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!

gpol
  • 966
  • 2
  • 19
  • 30

1 Answers1

7

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:

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • Thanks, I followed your approach and everything seems to be rolling out ok now. – gpol Oct 29 '12 at 09:24
  • I try to use the script but I get "remote: hooks/pre-receive: 10: hooks/pre-receive: Syntax error: "(" unexpected (expecting "fi")". I comes from this line "excludes=( ^$oldrev )" – cwhsu Sep 26 '14 at 11:06
  • @cwhsu strange, I don't get the error in my environment. – VonC Sep 26 '14 at 11:08
  • @VonC I will try it on other machine. I see this script in other thread as well and no one complains about it. This makes me so confused... Anyway, thanks for the reply. – cwhsu Sep 26 '14 at 11:12
  • @Vonc okay, I change a machine and still encounter some issues, first "./pre-receive: line 9: [: =: unary operator expected". By changing $oldrev = 0000000000000000000000000000000000000000 to "$oldrev" = 0000000000000000000000000000000000000000, this error is fixed. However, then I see the message "fatal: bad revision '^'" I think it has something to do with the bad branch or commit? – cwhsu Sep 26 '14 at 11:26
  • 1
    @cwhsu yes, that seems related to your current `git status` of your repo. I have edited the answer to add the double-quotes. – VonC Sep 26 '14 at 11:27
  • @VonC It seems that it happens because I use this pre-receive hook on my server-side. I think this is the reason. But due to my lack of understanding to your entire script, I am not sure why this cannot be run on server-side. Do you have any clue? – cwhsu Sep 26 '14 at 11:33
  • @cwhsu It should be used on a server-side, in a bare repo/hooks folder. Are you also using it in the context of a gitolite? – VonC Sep 26 '14 at 11:34
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/61978/discussion-between-cwhsu-and-vonc). – cwhsu Sep 26 '14 at 11:35
  • Ok, for those who have issues using this answer maybe this is just because we are not using gitolite. But if you're trying to write a server side hook with shell script. You probably want to take a look at this thread. http://stackoverflow.com/questions/22546393/can-git-pre-receive-hooks-evaulate-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 http://stackoverflow.com/questions/18977462/git-sha1-0000000000000000000000000000000000000000-all-zeroes-is-this-normal – cwhsu Oct 14 '14 at 01:15
  • One last thing in this line "excludes=( ^$oldrev )", the '^' simply means exclude! Don't think too much. – cwhsu Oct 14 '14 at 01:18
  • @cwhsu good points. I have included your comments in the answer for more visibility. – VonC Oct 14 '14 at 06:03