当Git pre-push
挂钩脚本正常工作时,如何获取完整的git push
命令内容?
例如,当我运行:git push origin master
时,执行预推钩
我想得到origin
&这个钩子里有master
。
如何获取参数列表?
答案 0 :(得分:5)
你的钩子脚本(假设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