如何将Git的分支名称添加到提交消息中?


102

我需要有关Bash脚本的一些帮助,该脚本会自动将git的分支名称添加为提交消息中的哈希。


3
对于任何来这里的人来说,最好的答案似乎是在页面底部
Ben Taliadoros

旁注:git branch | grep ...获取当前分支的所有方法都是错误的方法。考虑git symbolic-ref -q HEAD(如本答案所示)或git rev-parse --abbrev-ref HEAD。如果您在分离的HEAD上,symbolic-ref命令将失败,因此,如果您希望检测到这种情况,请使用它。否则,rev-parse --abbrev-ref方法可能是最好的。
torek

Answers:


53

使用prepare-commit-msgcommit-msg githook

PROJECT/.git/hooks/目录中已经有示例。

作为安全措施,您将必须在要使用它的每个存储库上手动启用此类挂钩。但是,您可以提交脚本并将其在所有克隆上复制到.git/hooks/目录中。


谢谢领导。谢谢。如果您可以通过脚本本身进一步帮助我,我将不胜感激:)
Tomer Lichtash 2011年

5
我不需要,您已经有一个示例可以完全满足您的要求,正如我已经在中说过的那样.git/hooks/prepare-commit-msg.sample。=)您需要进行的所有修改(按照注释中的说明进行操作)都是从stackoverflow.com/questions/1593051/复制粘贴任何解决方案
……

4
@ninjagecko,对我来说.git/hooks/prepare-commit-msg.sample包含三个示例。一个用于注释冲突部分,向其中添加git diff --name-status -r输出并添加签名行...无需在提交消息中添加分支名称。所以我被迫写自己的钩子。
shytikov 2012年

1
这是否you will have to manually enable such a hook on each repository you wish to use it意味着您必须授予FILE执行权限?如果是这样,我可以编辑答案以包括该答案吗(或者,可以吗?)?
丹·罗森斯塔克

1
为什么这是答案?更像是让我用Google帮您搜索。@shytikov的答案应该选择
TheRealFakeNews

177

这是我的commit-msg脚本示例:

#!/bin/sh
#
# Automatically adds branch name and branch description to every commit message.
#
NAME=$(git branch | grep '*' | sed 's/* //') 
DESCRIPTION=$(git config branch."$NAME".description)

echo "$NAME"': '$(cat "$1") > "$1"
if [ -n "$DESCRIPTION" ] 
then
   echo "" >> "$1"
   echo $DESCRIPTION >> "$1"
fi 

创建以下提交消息:

[branch_name]: [original_message]

[branch_description]

我使用的问题编号为branch_name,问题说明放置在branch_descriptionusing git branch --edit-description [branch_name]命令中。

您可以在此问答中找到有关分支描述的更多信息。

该代码示例存储在下面的Gist中


8
该脚本将多行提交消息压缩为一行。我用以下命令替换了您的echo语句:echo -n“ $ NAME”':'| cat-“ $ 1”> / tmp / out && mv / tmp / out“ $ 1”
Alex Spence 2014年

4
将此文件放入文件夹PROJECT / .git / hooks /
catanore 2015年

2
它运作良好。但是对于Mac,我也必须设置权限才能使其正常工作:>>> sudo chmod 755 .git / hooks / commit-msg
Manoj Shrestha

1
@ManojShrestha是的,它必须是可执行文件
David Mann

2
@AlexSpence更简单,您可以使用echo $NAME: "$(cat $1)" > $1。之所以可行,是因为丢失了换行符,原因是echo将的每行都$(cat "$1")当作一个新的参数,并在每行之间加一个空格。通过$(cat "$1")用双引号引起来,echo将cat输出视为单个参数。我也不认为有必要报价,$1因为它的价值是.git/COMMIT_EDITMSG
PiersyP

30

稍微简单一些的脚本,它将分支名称添加到提交消息之前您编辑。因此,如果您想更改或删除它,可以。

创建此文件.git / hooks / prepare-commit-msg

#!/bin/bash

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

firstLine=$(head -n1 $1)

if [ -z "$firstLine"  ] ;then #Check that this is not an amend by checking that the first line is empty
    sed -i "1s/^/$branchName: \n/" $1 #Insert branch name at the start of the commit message file
fi

4
我得到:sed: 1: ".git/COMMIT_EDITMSG": invalid command code .使用时。
亚当·帕金

1
啊哈,Mac OSX的不同之处,请参见:hintsforums.macworld.com/showpost.php?p=393450&postcount=11以解决此问题
Adam Parkin

2
就像检查修正案和
修理

3
OSX:如果收到上述错误消息,则需要文件扩展名才能工作。sed -i '.bak' "1s/^/$branchName : \n/" $1
canintex

您可以将其@用作sed分隔符,/因为分支名称或提交消息中更可能出现正斜杠,从而造成乱码sed
Ory乐队

28

您可以结合使用prepare-commit-msg和pre-commit挂钩来做到这一点。

.git / hooks / prepare-commit-msg

#!/bin/sh

BRANCH=`git branch | grep '^\*' | cut -b3-`
FILE=`cat "$1"`
echo "$BRANCH $FILE" > "$1"

.git / hooks / pre-commit

#!/bin/bash

find vendor -name ".git*" -type d | while read i
do
        if [ -d "$i" ]; then
                DIR=`dirname $i`
                rm -fR $i
                git rm -r --cached $DIR > /dev/null 2>&1
                git add $DIR > /dev/null 2>&1
        fi
done

设定权限

sudo chmod 755 .git/hooks/prepare-commit-msg
sudo chmod 755 .git/hooks/pre-commit

请注意,如果您使用的--amend是例如,这可以删除原始的提交消息。除了使用之外,echo还应该使用sed。它在一个衬里中:sed -i "1s@^@$(git branch | grep '^\*' | cut -b3-) @" $1
Ory乐队

10

将以下代码添加到prepare-commit-msg文件中。

#!/bin/sh
#
# Automatically add branch name and branch description to every commit message except merge commit.
#

COMMIT_EDITMSG=$1

addBranchName() {
  NAME=$(git branch | grep '*' | sed 's/* //') 
  DESCRIPTION=$(git config branch."$NAME".description)
  echo "[$NAME]: $(cat $COMMIT_EDITMSG)" > $COMMIT_EDITMSG
  if [ -n "$DESCRIPTION" ] 
  then
     echo "" >> $COMMIT_EDITMSG
     echo $DESCRIPTION >> $COMMIT_EDITMSG
  fi 
}

MERGE=$(cat $COMMIT_EDITMSG|grep -i 'merge'|wc -l)

if [ $MERGE -eq 0 ] ; then
  addBranchName
fi

它将为合并消息添加分支名称,但merge-commit除外。默认情况下,merge-commit具有分支信息,因此不需要多余的分支名称,并且使消息难看。


1
因此,当在消息上找到单词merge时,这不会修改提交消息吗?
thoroc '16

1
@thoroc在技术上是正确的;但是,在正常使用中,这没什么大不了的。在编辑它们之前,要解析的提交消息是“默认消息”。因此,只要您的提交模板中没有单词“ merge”,我相信您就可以了(只要其他“默认”消息除了默认的合并提交消息外就没有)。我本来误解了这一点,并且相信我现在已经纠正了。
新手C

5

蒂姆(Tim)的答案基于最重要的答案,结果证明了prepare-commit-msg钩子将发生哪种提交作为参数。。从默认的prepare-commit-msg中可以看到,如果$ 2是'merge',则它是一个合并提交。因此,大小写开关可以更改为包括Tim的addBranchName()函数。

对于如何添加分支名称以及默认prepare-commit-msg.sample钩子的所有未注释部分,我都有自己的偏好。

准备提交消息

#!/bin/sh

addMyBranchName() {
  # Get name of current branch
  NAME=$(git branch | grep '*' | sed 's/* //')

  # First blank line is title, second is break for body, third is start of body
  BODY=`cut -d \| -f 6 $1 | grep -v -E .\+ -n | cut -d ':' -f1 | sed '3q;d'`

  # Put in string "(branch_name/): " at start of commit message body.
  # For templates with commit bodies
  if test ! -z $BODY; then
    awk 'NR=='$BODY'{$0="\('$NAME'/\): "}1;' $1 > tmp_msg && mv tmp_msg "$1"
  else
    echo "title\n\n($NAME/):\n`cat $1`\n" > "$1"
  fi
}

# You might need to consider squashes
case "$2,$3" in
  # Commits that already have a message
  commit,?*)
  ;;

  # Messages are one line messages you decide how to handle
  message,)
  ;;

  # Merge commits
  merge,)
    # Comments out the "Conflicts:" part of a merge commit.
    perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1"
  ;;

  # Non-merges with no prior messages
  *)
    addMyBranchName $1
  ;;
esac

4

如果要使其全局(对于所有项目):

创建git-msg包含shytikov的答案内容的文件,并将其放在某个文件夹中:

mkdir -p ~/.git_hooks
# make it executable
chmod a+x ~/.git_hooks/commit-msg

现在启用挂钩:

git config --global init.templatedir '~/.git_hooks'

git init在每个要使用它的项目中。


2
我发现要使用此功能,我必须将“ c​​ommit-msg”放入为“ init.templatedir”配置的目录内的“ hooks”目录中,以便在将整个templatedir复制到“ git init”时使用“ commit- msg”最终位于项目的“ .git / hooks”目录中。

2

由于它们使用BSD sed而不是GNU 的事实,使这些解决方案在MacOS上运行时遇到了问题sed。我设法创建了一个简单的脚本来完成这项工作。仍在使用.git/hooks/pre-commit

#!/bin/sh
BRANCH=$(cat .git/HEAD  | cut -d '_' -f2)
if [ ! -z "$BRANCH" ]
then
    echo "$BRANCH" > "/Users/username/.gitmessage" 
else
    echo "[JIRA NUMBER]" > "/Users/username/.gitmessage"
fi 

这假设分支命名标准类似于functional-desc_JIRA-NUMBER。如果您的分支机构名称仅是您的Jira机票号码,那么您就可以摆脱管道和f2的所有限制。它还要求您.gitmessage在主目录中有一个名为的文件。


2

如果要将JIRA票证添加到提交消息中,请使用以下脚本。

提交类似的消息 PROJECT-2313: Add awesome feature 这样的这要求您的分支机构名称以jira Ticket开头。

这是以下解决方案的组合:

使用OS对其进行了修改,sed -i '.bak'并且在SourceTree中也可以正常使用。

https://gist.github.com/georgescumihai/c368e199a9455807b9fbd66f44160095

#!/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

这在客户端文件上运行良好:prepare-commit-msg以自动填充提交前缀。但是,如果我想在服务器端挂接(在我的情况下为bitbucket服务器)上做同样的事情,并且尝试在Bitbucket服务器路径的预接收挂接上添加以下逻辑:BITBUCKET_HOME / shared / data / repositories / <repository-id> / hooks / 21_pre_receive,尽管我从客户端的Feature / abc分支提交,但它不能作为“ git symbolic-ref -q HEAD”给予“ master”。这里还有别的办法吗?
santhosh
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.