KISS

Keep It Simple Stupid

git hook to insert ticket number

| comments

Updated on 2021-06-02: An extended version of the script is described here: Checkout PR script.

We have a rule on the project where every commit (and PR) should include the ticket number that it’s related to; by convention, it goes at the beginning of the commit message’s title, e.g. “US123: Display relative date when it’s closer than one day”. The rule also extends to the branch name, e.g. userStory/US123_display_relative_date. This makes it convenient to automate the insertion of the ticket number into the commit message, which is possible to do locally using git hooks.

I came up with this prepare-commit-msg hook a few years ago and have been improving it slightly over the years:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env bash
#
# A hook script to ensure that the commit message is prepended with a ticket
# number from the current branch name. The hook runs before the user edits
# the message.
#

COMMIT_MSG_FILE="$1"
# Can be: <empty>, `message`, `template`, `merge`, `squash`, `commit`.
# See `man githooks`.
#COMMIT_SOURCE="$2"
#SHA1="$3"

BRANCH="$( git rev-parse --abbrev-ref HEAD )"
TICKET_NUMBER="$( echo "$BRANCH" | grep -Eo '(US|DE|TA|F)\d+' )"
[[ -z "$TICKET_NUMBER" ]] || perl -pi -e "$.==1 && s/^(?!$TICKET_NUMBER:|fixup!)/$TICKET_NUMBER: /" "$COMMIT_MSG_FILE"

The script should be put into your working directory’s .git/hooks/prepare-commit-msg. It will run automatically for every commit before the user edits the commit message.

What it does is:

  • stores the filepath to the file, which the user then will edit to write the commit message, in COMMIT_MSG_FILE — this is a more semantic name then $1,
  • gets the current branch name into the BRANCH variable,
  • extracts a ticket number from the branch name with grep,
  • and if there is one and the first line of the commit message file doesn’t start with it yet (which may happen e.g. during git rebase), it prepends the number to the first line. It was easier to implement this regex with perl rather than sed, because the latter supports addresses (to update the first line only) but not negative lookahead.

Also, the script doesn’t add the ticket number if the commit message starts with fixup!, which is a very convenient feature of git. If you want to edit the latest commit, you can git commit --amend, but if you want to edit e.g. the third commit back, you can do your changes, git commit --fixup=@~3 to record that they should be integrated into that commit (this will create a new commit with the message fixup! 123abcd), then git rebase -i --autosquash master to rebase your branch onto your base branch and automatically merge the fix into the original commit. See more for example here: https://www.mikulskibartosz.name/git-fixup-explained/.

As for the ticket names, you may have a uniform name for all kinds of tickets in your project, e.g. PROJ123, or a different prefix based on the ticket type, such as US123 for user stories, DE234 for bugs/defects, TA345 for user stories’ tasks, etc. The script supports the latter case where it extracts one of the possible matches: grep -Eo '(US|DE|TA|F)\d+', which can be US or DE or TA or F followed by 1+ digits.

Given that I use it every working day dozens of times, the hook works very well in all cases that I’ve had: commit, amend, rebase, merge, fixup.

There is a more extended version of the hook that supports local PR branches. It’s based on my other script to check out those PRs, and I covered it in another blog post.

There are many other interesting things that can be done with git hooks. For more information about them, run man githooks or visit https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks or https://githooks.com/.

git

Note: The comments in the blog are provided by disqus.com; if you don't see the comment form under the post, probably your browser or its extension (such as uBlock Origin or NoScript) blocks their scripts.

« Analytics on this blog Checkout PR script »

Comments