Skip to content

Instantly share code, notes, and snippets.

@jalopez
Forked from jeremy-w/jira-prepare-commit-msg
Created January 16, 2023 12:27
Show Gist options
  • Save jalopez/e80206296fdf6e95902cf0ec0ef4ba5d to your computer and use it in GitHub Desktop.
Save jalopez/e80206296fdf6e95902cf0ec0ef4ba5d to your computer and use it in GitHub Desktop.
A git hook to tag your commits with the JIRA issue ID. Requires a git client that runs the hook like Git Fork, Git Kraken, or anything TUI/CLI.
#!/bin/bash
#
# jira-prepare-commit-msg: Easy commit tagging for Jira
#
# https://gist.github.com/jeremy-w/818b2980f0d9768da83249458aa67678
#
# If you name your branch to include the Jira issue key,
# this hook will automatically add the issue key to your commit messages.
# This makes it easy to trace work back to Jira, and it also means
# your commits show up in the Activity tab for that issue.
#
# To enable this hook:
#
# cd gitRepoParentDirectory
# ln -sf PATH/TO/jira-prepare-commit-msg */.git/hooks/prepare-commit-msg
#
# Execution context:
#
# - called by `git commit` in the git directory
#
# Parameters:
#
# - $1 is the filename holding the commit message. It already has stuff in it.
# - $2 is the commit message source (message, template, squash, commit, ...)
# - $3 is a commit ID - it's only present committing with -c, -C, or --amend
#
# The hook's purpose is to edit the commit
# message file, $1. If the hook fails with a non-zero status,
# the commit is aborted.
#
# Jeremy W. Sherman (@jeremy-w on GitHub)
# 2019-04-05
#
# 2020-05-19:
# * NEW: Use jira.baseUrl config variable, if present, to include a link rather
# than just the issue ID in the commit messages.
# Example: git config --set jira.baseUrl https://YourCorp.atlassian.net/browse
#
# 2021-11-02:
# * FIXED: With newer git versions, the first commit on a branch was not
# picking up the branch name.
PROGNAME=$0
function debug() {
# comment out next line to shut it up, uncomment to get some output
#echo "$PROGNAME: $*" >&2
:; # empty functions aren't allowed, so here's a NOP
}
debug "Begun. Args: $*"
# Project Key format is configurable, but defaults to roughly this.
# https://confluence.atlassian.com/adminjiraserver/changing-the-project-key-format-938847081.html
ISSUE_REGEX="([A-Z]{1}[A-Z0-9_]{1,}-[0-9]{1,})"
if test "x$ISSUE_ID" = x; then
# Infer from beginning of branch name.
# While rev-parse is more accurate, it used to not work during rebase, but on
# recent versions, reports HEAD, while describe reports a hash alone.
# See: https://github.com/git/git/blob/041f5ea1cf987a4068ef5f39ba0a09be85952064/contrib/completion/git-prompt.sh#L446-L447
branch=$(git rev-parse --abbrev-ref HEAD || git describe --contains --all --always)
debug "Issue ID unset; inferring from branch: $branch"
if [[ "$branch" =~ ^$ISSUE_REGEX ]]; then
ISSUE_ID=${BASH_REMATCH[1]}
debug "Inferred ISSUE_ID=$ISSUE_ID"
fi
fi
case "$2,$3" in
merge,)
debug "Commenting out those conflicts lines for ya."
/usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;
# The checks here are:
# - do we have an issue id to inject?
# - is there already one in the message body that's not commented out?
# (this avoids treating the ID in the branch name as an already-present ID)
*) if test \! "x$ISSUE_ID" = x && ! grep "^[^#]" "$1" | grep -E -q "$ISSUE_REGEX"; then
debug "Detected no issue ID in commit body. Adding it now as $ISSUE_ID."
# If we have URL info, then use that.
JIRA_ISSUE_URL_BASE=$(git config --get jira.baseUrl)
if test \! "x$JIRA_ISSUE_URL_BASE" = x; then
debug "Detected JIRA_ISSUE_URL_BASE of $JIRA_ISSUE_URL_BASE."
ISSUE_ID="$JIRA_ISSUE_URL_BASE/$ISSUE_ID"
debug "ISSUE_ID has been updated to $ISSUE_ID."
fi
# Place the issue ID after the commit message.
printf '\n\n%s\n' "$ISSUE_ID" >> "$1"
# If GIT_EDITOR is literally a colon character, there is no editor.
# Otherwise, append some comments to help the person editing the
# commit message.
if test \! "$GIT_EDITOR" = :; then
debug "Running interactive - adding some Smart Commit Syntax advice."
cat <<EOT >> "$1"
# You can log time, add comments, and trigger
# transitions using Smart Commit syntax.
#
# Example:
# JRA-123 JRA-234 JRA-345 #resolve #time 2d 5h #comment Task completed ahead of schedule
#
# See: <https://confluence.atlassian.com/fisheye/using-smart-commits-960155400.html>
EOT
fi
else
debug "Either no ISSUE_ID was detected, or there appears to be an issue ID already in the commit body."
debug " ISSUE_REGEX=$ISSUE_REGEX"
debug " ISSUE_ID=$ISSUE_ID"
debug " Commit body:\n$(cat "$1")"
fi;;
esac
debug "Done."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment