How do I require specific text in a git commit message?

You have your own git server (either on-premise gitlab or something else), and you want to require your developers to have certain text in their git commit messages, like the work item number it falls under, or the ticket number.

To solve this, you need to create a git hook, which is just a file that goes into your gitlab server. The file goes into your /data/opt/gitlab/git-data/repositories/my_project.git/custom_hooks directory. You may need to use sudo -i to cd to this directory.

The hook you’ll create is called a pre-receive hook, and it is specifically meant to check all commits before adding them to the remote repository.

pre-receive hook that requires certain text to be in the commit message is below:

#!/bin/python
import sys
import re
import subprocess


#Format: "oldref newref branch"
line = sys.stdin.read()
(base, commit, ref) = line.strip().split()
new_branch_push = re.match(r'[^1-9]+', base)
branch_deleted = re.match(r'[^1-9]+', commit)
contains_commit_msg = False
if not new_branch_push:
    revs = base + "..." + commit
    proc = subprocess.Popen(['git', 'rev-list','--oneline','--first-parent', revs], stdout=subprocess.PIPE)
    lines = proc.stdout.readlines()
    if lines:
        for line in lines:
            rev = str(line)
            match = re.search(r'TICKET-[0-9]{2,5}|#NEX-[0-9]{2,5}|HOTFIX|FORCE', rev)
            if match is not None:
                contains_commit_msg = True
if contains_commit_msg or new_branch_push or branch_deleted:
    exit(0)
else:
    print "Commit does not contain the story associated with the commit in the format: TICKET-123 or #TICKET-123"
    exit(1)

The code is in python.

The pre-receivehook will receive a list of commit hashes in the form of:

ab3c291835832c309 b2fed56890cab348 new-branch

where the first hash is the old commit, the second is the new commit, and the branch name is the third.  This also means you can use this hook to ensure branch names meet a certain criteria.

Deleted branches will have zeros for the second commit, and new branches will have all zeros for the first commit. and those would cause errors (since new branches really don’t have a commit message; and deleted branches don’t have one either); and this code handles that.

If you want specific text to be in the ticket, this line handles that:

match = re.search(r'TICKET-[0-9]{2,5}|#TICKET-[0-9]{2,5}|HOTFIX|FORCE', rev)

Just change the text in r''to your own python regular expression. You can test your python regular expression at pythex.org.

This regular expression says that the ticket must have the word “Ticket”, followed by a dash, followed by a 2-5 digit number, or it must have a pound sign in front of “Ticket” followed by a dash, followed by a 2-5 digit number, or it must have the word HOTFIXin all caps, or it must have the word FORCE in all caps.

Once you have your pre-receive hook in the right directory, you must do three things:

  1. Change the owner to the gituser (the user account that will run this command):

chown git:git pre-receive

  1. Make the command executable.

chmod +x pre-receive

  1. Change the owner of the custom_hooksdirectory to git.

chown git:git pre-receive /data/opt/gitlab/gitdata/repositories/my_project.git/custom_hooks

I keep an up-to-date version of this pre-receive hook on my github page.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s