It's not the same without you

Join the community to find out what other Atlassian users are discussing, debating and creating.

Atlassian Community Hero Image Collage

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.

4 answers

1 accepted

0 votes
Answer 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.

Thanks.

I made a small improvement to the script posted above.

I combined your answer with this solution from stack overflow

 

#!/bin/sh
#
# A hook script to prepare the commit log message.
# If the branch name it's a jira Ticket.
# It adds the branch name to the commit message, if it is not already part of it.

branchPath=$(git symbolic-ref -q HEAD) #Somthing like refs/heads/myBranchName
branchName=${branchPath##*/} #Get text behind the last / of the branch path

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

sed -i '.bak' "1s/^/$jiraTicketName: /" $1 #Insert branch name at the start of the commit message file
fi
# else => do not edit the commit message.

I wonder why source tree does not act as $EDITOR mentioned in accepted answer.

Source Tree could have executed prepare-commit-msg to receive dynamically produced commit message and populate it in text area within source tree commit dialog.

User than can than review message, customize it and hit "commit" button to finish committing.

Commit template is static, it's not really an alternative to scripted prepare-commit-msg.

Suggest an answer

Log in or Sign up to answer
TAGS
Community showcase
Published in Sourcetree

Sourcetree for Windows - CVE-2019-11582 - Remote Code Execution vulnerability

A vulnerability has been published today in regards to Sourcetree for Windows.  The goal of this article is to give you a summary of information we have gathered from Atlassian Community as a st...

4,917 views 0 12
Read article

Community Events

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

Find an event

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

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you