在预推钩中,得到" git push"命令全部内容?

时间:2017-02-25 11:32:48

标签: git shell githooks git-push

当Git pre-push挂钩脚本正常工作时,如何获取完整的git push命令内容?

例如,当我运行:git push origin master时,执行预推钩 我想得到origin&这个钩子里有master

如何获取参数列表?

3 个答案:

答案 0 :(得分:5)

TL; DR摘要:你需要一个while循环

你的钩子脚本(假设sh / bash)应该包含一个形式的循环:

while read localname localhash remotename remotehash; do
    ... code here using $localname etc ...
done

描述

所有Git钩子都在the githooks page中描述。 pre-push挂钩描述以:

开头
  

此挂钩由 git push 调用,可用于防止推送发生。使用两个参数调用钩子,这两个参数提供目标远程的名称和位置,如果未使用命名远程,则两个值都相同。

     

有关要推送内容的信息在钩子的标准输入上提供了以下形式的行:

<local ref> SP <local sha1> SP <remote ref> SP <remote sha1> LF
     

例如,如果运行命令git push origin master:foreign,则挂钩将收到如下所示的行:

refs/heads/master 67890 refs/heads/foreign 12345
     

虽然将提供完整的40个字符的SHA-1。 ...

第一段意味着在shell脚本中,$1$2是远程的名称 - 例如,origin - 及其URL,或者URL重复两次,如果用户运行:

git push https://some.host.name/some/path ...

第二个段落重要git push命令可以推送多个分支。例如,我可以运行:

git push origin feature-A feature-B

推送feature-A feature-B。您必须读取所有输入行,一次一行,以发现要推送的内容。存储库中的当前分支并不重要:读取HEAD将给出错误的答案,除非用户碰巧正在推送当前分支。另一方面,大多数用户大多只是推动当前分支。这会让你觉得你的钩子是100%可靠的,当它实际上只有92.37%可靠时。 1

如文档所述,钩子获取每个引用的全名。如果您正在推送分支,则该全名以refs/heads/开头,但您可以推送标记,在这种情况下,全名以refs/tags/开头。要编写一个可靠的钩子,你必须检查全名,而不是简单地剥离前两个组件。 2

1 与38.61%的统计数据一样,这个数据当场弥补。 : - )

2 有许多不良的样本钩子(不是所有的预推钩子)都在那里使用:

branch=$(echo $ref | cut -d/ -f3)

如果您正在推送标记v2.3,则此挂钩会认为您正在推送名为v2.3分支。如果您正在推送名为bugfix/1234的分支,它会认为您正在推送名为bugfix的分支! cut技术是错误的,但对后者的快速解决方法是使用-f3-,这至少会产生bugfix/1234。最好验证参考文献的第一个组成部分,例如:

case $ref in
refs/heads/*) ... it's a branch ...;;
refs/tags/*) ... it's a tag ...;;
*) ... it's something else entirely, such as refs/notes/* ...;;
esac

知道前缀后,您可以使用${ref#refs/heads/}${ref#refs/tags/}去除已知前缀并获取完整但不合格的分支或标记名称。但是,如果遇到很多情况,您可以直接使用完整的参考名称。

答案 1 :(得分:0)

这些参数作为命令行参数传递给钩子,你可以从那里获取它们。 E.g:

#!/bin/sh

remote="$1"
url="$2"

echo "remote: $1 ; url $2"

exit 0

答案 2 :(得分:-1)

这些参数传递到钩子

在钩子中你可以得到这样的分支名称:

branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')

如果您希望在终端中查看这些设置而不是脚本的一部分,请使用以下命令:

# get the name of the tracking branches
git branch -a -vv

# or: 
git status -b --porcelain

# to get the name of the current branch:
git symbolic-ref -q HEAD

如何绕过pre-push挂钩?

git push --no-verify