BitLoop Blog

Linking your Git commits with ticket numbers

In this post, I want to share a small “trick” that we here at BitLoop are using to link git commit messages with a ticket-based system like Redmine or Jira.

Tracking and linking git commits with tickets can be useful when promoting/deploying different tickets to specific environments or cherry-picking different tickets (which can have multiple commits). When tickets are not linked with commits and there are many commits in the main branch of your project it is hard to do these operations because there is no easy way to identify which commit belongs to which ticket.

The solution described in this post is to perpend every git commit message automatically with a ticket number using a git hook.

You can read more here about what git hooks are and how they work: https://githooks.com/

For this solutions we will use prepare-commit-msg hook and the script will extract the ticket number from the branch name, so this will mean that your branch naming strategy should contain the ticket number.

For example if we have a ticket in our ticketing system like #15104 - Server Info tab under Global settings based on our internal branch naming convention the developer working on this ticket will create a git branch named: feature/15104-server-info-tab-under-global-settings. Using this naming convention we can use the following script to automatically prepend every commits with the ticket ID.

So when adding a comment like:

git commit -m "Added DB migrations for Server Info

(or from any git client) will result in a git commit message like:[15104] Added DB migrations for Server Info

Having this solution your git commit history will look like this:

which clearly shows which commit belongs to which ticket.

Steps to set up this hook:

  1. Create a folder where you will store your global git hooks ex: d:\.git-templates\
  2. Configure hooksPath (using built-in Command Prompt cmd)
    • git config --global core.hooksPath d:\.git-templates
  3. Add the following two files to folder:
    • prepare-commit-msg
    • #!C:/Program\ Files/Git/usr/bin/sh.exe
      
      exec powershell.exe -NoProfile -ExecutionPolicy Bypass -File "d:\.git-templates\prepare-commit-msg.ps1" $1 $2 $3

      prepare-commit-msg.ps1

    • param ($commit_msg_file, $commit_source, $sha1)
      $commit_msg = Get-Content ($commit_msg_file)
      $branch_name=$(git symbolic-ref --short HEAD)
      
      $ticket_id_found = $branch_name -match '(^|\/)?(((\w*)-)?(\d+))-'
      
      # do not prepend prefix if ticket number was not found
      if ($ticket_id_found)
      {
          $ticket_id = $Matches[2]
          $commit_prefix = '['+$ticket_id+'] '
          
          # do not prepend if already there (e.g. when doing an amend to an existing commit)
          if ($commit_msg.StartsWith($commit_prefix) -eq $false)
          {
              Set-Content $commit_msg_file ($commit_prefix + $commit_msg)
          }
      }

Note: