31

So my branch is named after bugtracker ticket number, something like "issue-1234", and we have a convention to always write down ticket number in commit message. I'm wondering if it's possible to append the ticket number in commit message automatically when I'm working on an issue-* branch without me explicitly typing it.

I looked at git commit hooks, namely pre-commit, prepare-message, and post-commit, and none of them seem to be able to do what I wanted. Post-commit hook comes close, but you cannot modify the message that's committed with -m.

To reiterate, I'm wondering if this is possible:

On branch: issue-1234

git commit -a -m"fixed this pesky issue"

After the commit, in git log, it shows the message as:

fixed this pesky issue. ticket number: #1234
EnToutCas
  • 1,297
  • 2
  • 15
  • 20

7 Answers7

24

You missed a hook. The one you want is commit-msg:

This hook is invoked by git commit, and can be bypassed with --no-verify option. It takes a single parameter, the name of the file that holds the proposed commit log message. Exiting with non-zero status causes the git commit to abort.

So for example:

#!/bin/sh

ticket=$(git symbolic-ref HEAD | awk -F- '/^issue-/ {print $2}')
if [ -n "$ticket" ]; then
    echo "ticket #$ticket" >> $1
fi

That's a very naive parsing of your branch name, and it's simply appended to the commit message on its own line. Modify it if that's not good enough for you.

Of course, I'd actually recommend doing this in prepare-commit-msg, and committing with git commit (without -m). It's very, very rare that you can actually write sufficient information in a single-line commit message. Further, that will let you see the message before the commit is made, in case your hook doesn't do quite what you want.

Cascabel
  • 479,068
  • 72
  • 370
  • 318
  • +1. If you do redirect your multi-line comment in a file, a do a `git commit --file=myMultiLineCommentFile`, you still can use `commit-msg`hook, right? – VonC Apr 28 '11 at 21:51
  • @VonC: The `commit-msg` hook fires whenever a commit is made - with the exception of fully automatic merge commits (i.e. no conflicts, no `--no-commit`). That shouldn't be an issue for the OP, though. (This is a bit of a bug/oversight, really. Just recently they added support for the `prepare-commit-msg` hook for automatic merges, but I believe `post-commit` and `commit-msg` are still missing.) – Cascabel Apr 29 '11 at 01:18
  • I think `git symbolic-ref HEAD` is always start with `refs/heads` instead of `issue`? – xi.lin Dec 06 '15 at 15:10
  • `-m` can be given multiple times, each contributing a new line to the commit message. This is how I commit most times; the string passed to `-m` can also be a multi-line string in itself, but how that's constructed is shell-specific. – Alex Povel Jul 18 '22 at 13:38
8

You can as well use prepare-commit-msg hook, which accepts more parameters than commit-msg. Then you can check if the message is coming from a file, a template, etc to avoid appending the issue numbers when you don't want it.

With the following script in .git/hooks/prepare-commit-msg when you are working in a feature branch named foo-123, then [#123] will be added to the third line of every commit you make.

More information in this post I wrote

#!/bin/sh

if [ x = x${2} ]; then
  BRANCH_NAME=$(git symbolic-ref --short HEAD)
  STORY_NUMBER=$(echo $BRANCH_NAME | sed -n 's/.*-\([0-9]\)/\1/p')
  if [ x != x${STORY_NUMBER} ]; then
    sed -i.back "1s/^/\n\n[#$STORY_NUMBER]/" "$1"
  fi
fi
Waiting for Dev...
  • 12,629
  • 5
  • 47
  • 57
  • This won't quite work as intended with `commit -m `, as it will pre-pend the story number to the commit message. If you replace `^` with `$` in the regex, then it should work in both cases. – Geekfish Apr 18 '18 at 16:29
4

This way you can add branch name to the start of commit message. It's prepare-commit-msg hook. Work both for "git commit -m" and "git commit" commands. The option is file .git/hooks/pre-commit.skip which contains a list of branches you don't want to auto-prepend.

BRANCH="$(git rev-parse --abbrev-ref HEAD)"
FILE_CONTENT="$(cat $1)"
skip_list=`git rev-parse --git-dir`"/hooks/pre-commit.skip"
if grep -E "^$BRANCH$" $skip_list; then
  exit
fi
if [ $2 = "message" ]; then
  echo $BRANCH: $FILE_CONTENT > $1
else
  echo $BRANCH: > $1
  echo $FILE_CONTENT >> $1
fi
offmind
  • 41
  • 2
4

Using pre-commit along with the giticket hook, works pretty well to have the ticket number in the commit automatically.

Milind
  • 560
  • 5
  • 5
2

Here's a complete solution for any kind of issue/ticket numbering commit messages:

prepare-commit-msg

#!/bin/bash
# Append issue number / bug tracking URL to commit.
#
# If the branch name contains the issue number, it will append it to the
# commit message. Example:
#
#   BRANCH NAME            LINE TO APPEND
#   feature/GH-123-emoji   GitHub: #123
#   WRIKE-123-add-payment  Wrike: https://www.wrike.com/open.htm?id=123
#   UNKNOWN-123            Issue: #123

branchName=`git rev-parse --abbrev-ref HEAD`

IFS=- read issueTracker issueNumber <<< $(echo $branchName | sed -nr 's,([a-z-]+/)?([A-Z]+-[0-9]+)-.+,\2,p')

if [[ -z $issueNumber ]]; then
  exit 0
fi

case "$issueTracker" in
  WRIKE)
    line="Wrike: https://www.wrike.com/open.htm?id=$issueNumber"
    ;;
  GH)
    line="GitHub: #$issueNumber"
    ;;
  GL)
    line="GitLab: #$issueNumber"
    ;;
  *)
    line="Issue: #$issueNumber"
    ;;
esac

# If the commit message already contains the line (`--amend`), then do
# not add it again.
if ! ( grep "$line" "$1" > /dev/null ); then
  sed -i.bak -e "/# Please enter the commit message for your changes./ s,^,$line\n\n," $1
fi

Put it into repository's .git/hooks directory to apply only to the repo, or set up core.hooksPath in ~/.gitconfig and copy to that directory to apply to all of your repositories.

See in my config files repository besides other usefull scripts.

bimlas
  • 2,359
  • 1
  • 21
  • 29
2

Another option would be to use git notes to add the ticket number information to the commit, using one of the hooks you mention.
(See "Notes to self" blog post entry for more on the notes mechanism)

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • the problem with hooks is that it doesn't really work if I already supply commit message with -m. prepare-commit-message hook only works when an external editor is fired up – EnToutCas Apr 28 '11 at 19:47
  • @EnToutCas: you mean you have no hook at all executing itself on a commit when the commit message is specified through `-m` ? – VonC Apr 28 '11 at 20:39
  • +1 For VonC as well. It's a nice feeling to be able to bathe in new knowledge every day. Stackoverflow rocks and it's the people of stackoverflow that make it so. – rtn Apr 28 '11 at 21:10
  • Notes are an interesting idea, but the shortcomings associated with sharing them kind of defeat the purpose of adding a ticket # to a commit (usually you do that so a remote can process those commit messages and create linkages between a ticket tracking system and a given commit). – Adam Parkin Jul 16 '13 at 20:31
0

As this maybe useful for somebody looking for quick solution - with possibility of improvement and quite good portability (adding this to a new box is matter of simple bash source git-tricks.sh)

Our branchnames are usually in the form: <work-category>/<ticket-id>-<short-description>

Like: bug/ID-1234-bad-button-color

I then have following aliases:

  • alias git-branch-name='git rev-parse --abbrev-ref HEAD'
    Output: bug/ID-1234-bad-button-color
  • alias git-branch-ticket='git-branch-name | grep -oP "^[^/]*/\K[^-]*-[0-9]+"'
    Output: ID-1234 (In case of author of the question it should be:'git-branch-name | grep -oP "^issue-\K[0-9]+"' )

And final one:

alias git-describe-commit='git commit --all --edit --message "[$(git-branch-ticket)] --edit this--"'

Which allows me to use git-describe-commit for quickly adding changes to the repo.

yatsek
  • 855
  • 1
  • 10
  • 19