SourceTree and git prepare-commit-msg

I want to prepare a commit message based on the name of the current branch. For testing I created .git/hooks/prepare-commit-msg looking like

#!/bin/sh

echo 1: $1
echo 2: $2
echo 3: $3

mv $1 $1.org
echo foo > $1.tmp
cat $1.tmp $1.org > $1

when I do "git commit" from cmd I get a commit message containing "foo" (and then some stuff git added).

From SourceTree I get an empty commit message in the commit message text box.

I had expected SourceTree to honour the hook.

3 answers

1 accepted

That hook is reliant on git calling the $EDITOR in response to a 'git commit' call with no message supplied. Since SourceTree is already running, that's not how it works - it pops up the commit dialog before ever calling git, and lets you type the message which it passes to git, which is why you don't see that hook being used.

Unfortunately that hook style really isn't compatible with anything other than a reactive text editor approach to committing, i.e. command line use.

I see. Would it at all be possible to add support for that hook? (spawning that hook as a shell script, provided you can find the correct shell to run it in, of course).

Another option would be to supply your own hook-mechanism. That way you could make hooks even better, by allowing a global hook with a per repository override option. Simply shell any application with the same parameters as the hook is called with before opening the commit dialog. The interface is only the command line and remnants on the file system anyway, which leads me to believe it should be a relatively unobtrusive change. Let me know if you want beta testers.

I see. Would it at all be possible to add support for that hook? (spawning that hook as a shell script, provided you can find the correct shell to run it in, of course).

Another option would be to supply your own hook-mechanism. That way you could make hooks even better, by allowing a global hook with a per repository override option. Simply shell any application with the same parameters as the hook is called with before opening the commit dialog. The interface is only the command line and remnants on the file system anyway, which leads me to believe it should be a relatively unobtrusive change. Let me know if you want beta testers.

It's quite a big change to the workflow to support the prepare-commit-msg hook just because it splits the commit action into 2, which is not how ST works - you prepare everything up front and then confirm it in 1 action. So I can't see us supporting that in future.

About alternative approaches, we do already support the 'commit.template' configuration variable to pre-fill the mesage in the commit dialog, and this can be set per-repository. What it can't do is support scripted templates at this time, so assuming 'foo' is not constant this probably doesn't solve your problem. It's something we could consider for the future but I do have to add a note of caution that the TODO list for the Windows version of SourceTree is quite long, given that it's already catching up with the Mac version. But if you want to open a feature request, here's where we track them: https://jira.atlassian.com/browse/SRCTREEWIN.

Steve,

Further testing yields that the hook is indeed running, just that it runs after commit-button is clicked. I was too focused on the message appearing in the textbox, so I didn't try doing an actual commit.

The existing behaviour is good enough for now.

Ah, thanks for the update - I didn't expect that, I thought git would only run it if it was going to launch the $EDITOR (ie no message provided to git commit). That's interesting then, I assume it just pre-pends your 'foo' text to whatever you type in SourceTree then?

Yes, that's right. I amended the script to not modify the message if it already starts with the branch name.

#!/bin/sh

branchname=$(git branch | grep ^* | sed 's/\* //g' | sed 's/f\///g')
if [ "$branchname" = "master" ]
	then
	exit
fi

originalmessage=`cat $1`

if [[ $originalmessage == $branchname* ]]
	then
	exit
fi

echo "$branchname - $originalmessage" > $1

Out feature branches are named "f/<jiraissue-###>" thus the stripping of f/.

The same thing happens in command line if I do git commit -m "some mesage". $EDITOR is not launched but the message is modified according to the script.

While Jesper's issue may be sorted out I still think in general some way to do the equivalent of prepare-commit-msg is important. I am the author of a prepare-commit-msg hook for integration with Pivotal Tracker (https://github.com/dalewking/PivotalTrackerGithook) that inserts comments into the commit message containing lines for the scm integration to add commit messages to pivotal messages. So if a commit finishes a particular story all I have to do is uncomment the generated comment line and the correct data is added to the commit message. Currently for my project using Pivotal I prepare the commit in source tree then jump to the terminal to do the commit so that I get the benefit of this hook.

I also need a similar thing for Jira. It currently is a pain when checking in to have to go to jira to look up the JIRA number to add to Jira. I would really like some way to automate this within source tree so some form of plugin mechanism for modifying commit messages would be nice. Does not have to be the git mechanism exactly, but some way to do it without jumping to command line would be nice.

My team works in an environment where almost all of our branch names contain a JIRA ticket name/number in the format "PROJECTNAME-123". I modified your script slightly to use a regex-capture to match the PROJECTNAME-123 portion of the branch name. 

 

#!/bin/sh


# Get the name of the current branch.
branchname=$(git branch | grep ^* | sed 's/\* //g')

regex="(PROJECTNAME-[0-9]*)"

if [[ $branchname =~ $regex ]]
then
    # Get the captured portion of the branch name.
    jiraTicketName="${BASH_REMATCH[1]}"

    originalmessage=`cat $1`


    # If the message already begins with PROJECTNAME-#, do not edit the commit message.
    if [[ $originalmessage == $jiraTicketName* ]]
        then
        exit
    fi

    echo "$jiraTicketName: $originalmessage" > $1
fi
# else => do not edit the commit message.

Hey, I stumbled upon this. I tried your above snippet. However, I ran into this issue:

`.git/hooks/prepare-commit-msg: line 23: gt: command not found`

I assume it's following line:

`echo "$jiraTicketName: $originalmessage" &gt; $1`

 

Edit: Figured it out. It should be

 

`echo "$jiraTicketName: $originalmessage" > $1`

Apparently when I pasted in the above code, the "greater-than symbol" got encoded to `&gt:`. I have fixed it above.

MK I'm New Here Mar 22, 2018

Thanks.

Suggest an answer

Log in or Sign up to answer
How to earn badges on the Atlassian Community

How to earn badges on the Atlassian Community

Badges are a great way to show off community activity, whether you’re a newbie or a Champion.

Learn more
Community showcase
Published May 11, 2018 in Sourcetree

Tip from the team: debugging Sourcetree

Supported Platforms macOS Windows If you're reading this and it's not just educational… we know you're unhappy right now and apologize for that   We're dedicated to improving yo...

138 views 0 5
Read article

Atlassian User Groups

Connect with like-minded Atlassian users at free events near you!

Find a group

Connect with like-minded Atlassian users at free events near you!

Find my local user group

Unfortunately there are no AUG chapters near you at the moment.

Start an AUG

You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs

Groups near you