在Git钩子中获取提交信息

49

我希望在Git提交之前检查提交信息。

我使用预提交钩子来实现,但是我无法在.git/pre-commit脚本中获取提交信息。请问如何获取?

7个回答

51
pre-commit钩子中,提交消息通常尚未创建1。您可能希望改用prepare-commit-msgcommit-msg钩子之一。在Pro Git的一个不错的章节中介绍了这些钩子的运行顺序以及通常可以使用它们做什么。 1. 特别情况是提交者可能已使用-m提供了提交消息,但是该消息仍然无法被pre-commit钩子访问,而可以被prepare-commit-msgcommit-msg访问。

1
请注意,这些是客户端脚本,对于服务器端脚本,可能需要使用“pre-receive”。 - Walty Yeung
the commit message hasn't been created yet yes it has .. when the user typed git commit -m "foobar" - user7898461
@OlegzandrDenman - 好的,没问题 - 我已经重新措辞了答案并添加了一个脚注关于那个问题。 - Mark Longair

25

我在 commit-msg 钩子中实现了这个功能。请参阅文档

commit-msg

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

my_git_project/.git/hooks下,我添加了文件commit-msg(必须使用此名称)。我在该文件中添加了以下Bash内容进行验证。

#!/usr/bin/env bash
INPUT_FILE=$1
START_LINE=`head -n1 $INPUT_FILE`
PATTERN="^(MYPROJ)-[[:digit:]]+: "
if ! [[ "$START_LINE" =~ $PATTERN ]]; then
  echo "Bad commit message, see example: MYPROJ-123: commit message"
  exit 1
fi

无法工作。我无法在提交消息钩子中获取提交消息。 COMMIT_FILE=$1 COMMIT_MSG=$(cat $1) - iKushal
应该是 commit-msg 而不是 commit.msg,对吧? - AFract
文件必须命名为 commit-msg,而不是 commit.msg。 - commbot
我该如何将提交信息存储到变量中?cat $1 不起作用... - Pawan Deore
它可以工作,谢谢,但只有在我去掉PATTERN中的引号时才有效,请参见https://dev59.com/GHI95IYBdhLWcg3wvwsQ#GrSiEYcBWogLw_1bwIZQ。 PATTERN=^\[.*-\d*\].* - PJ127

3
我已经在Bash中创建了一个commit-msg脚本,其中包含提交语法-<4_DIGIT_TICKETID>-。开发人员可以使用此语法对基于Azure DevOps票据ID的提交进行操作。
#!/bin/sh

# The below input_file is file ".git/COMMIT_EDITMSG" where commits are stored
INPUT_FILE=$1

# It will copy the commit string from ".git/COMMIT_EDITMSG"
START_LINE=`head -n1 $INPUT_FILE`

# Initial index value
sum=0

# Add commit in an array variable separated by -
IFS='- ' read -r -a array_value <<< "$START_LINE"

# Count array index
for i in ${!array_value[@]}
do
    sum=`expr $sum + $i`
done

# Verify commit
if [ ${sum} == 3 ]; then

BRANCH_NAME=`git branch | awk '/\*/ { print $2; }'`
TICKET_DIGIT=`awk -F '[0-9]' '{print NF-1}' <<< "${array_value[1]}"`

   if [ ${array_value[0]} != ${BRANCH_NAME} ];  then
        echo "please enter current branch name"
        exit 1
   fi

   if [ "${TICKET_DIGIT}" != "4" ];  then
        echo "INVALID TICKET ID"
        exit 1
   else
      echo "verify ticket ID ${array_value[1]}"
   fi

else
   echo "pattern must be <CURRENT_BRANCH_NAME>-<4_DIGIT_TICKETID>-<COMMIT_DECRIPTION> without space and don't use - in commit_description"
   exit 1
fi

非常感谢您提供的输入文件头命令,这真是帮了我一个大忙。链接地址:https://gist.github.com/phillpafford/02437d61a90a8d5f8cd520944a7b618c - undefined

3
钩子名称应该是:commit-msg,否则它将不会被调用:

是的,显然提交消息是传递给 commit-msg 的第一个参数,这也与文件 .git/COMMIT_EDITMSG 的内容相同。 - Alexander Mills
是的,在(示例)文件commit-msg.sample的第9行也这样写道:*'要启用此挂钩,请将此文件重命名为“commit-msg”。'* - Peter Mortensen

1

通常由commit-msg完成。
该钩子提供了一个包含提交信息的文件。
以下是一个示例,拒绝具有test单词的提交:

declare -r msg=$(< $1);
if grep -i test <<< "$msg" > /dev/null 2>&1; then
    echo you are not allowd to have test commit.
    exit 1;
else
    echo looks good.
    exit 0;
fi

因此,exit 1会阻止git继续执行,而挂钩中的exit 0则允许git继续执行。


注意
这里的$1是文件名:.git/COMMIT_EDITMSG


enter image description here


0

如果您想从除了commit-msg之外的钩子访问提交消息,可以读取文件.git/COMMIT_EDITMSG

简单的Python示例:(Git钩子可以使用#!/usr/bin/env python shebang运行Python)

#!/usr/bin/env python

from pathlib import Path

print(Path(".git/COMMIT_EDITMSG").read_text())

请确保根据您当前的工作目录正确获取相对路径


-1

您可以使用Python在服务器端的pre-receive钩子中执行以下操作,这将显示修订信息。

import sys
import subprocess
old, new, branch = sys.stdin.read().split()
proc = subprocess.Popen(["git", "rev-list", "--oneline","--first-parent" , "%s..%s" %(old, new)], stdout=subprocess.PIPE)
commitMessage=str(proc.stdout.readlines()[0])  

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接