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.
A 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-receive
hook 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 HOTFIX
in 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:
- Change the owner to the
git
user (the user account that will run this command):
chown git:git pre-receive
- Make the command executable.
chmod +x pre-receive
- Change the owner of the
custom_hooks
directory togit
.
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.