在 pre-push hook 中,获取 "git push" 命令的全部内容?

In pre-push hook, get "git push" command full content?

当Git pre-push hooks脚本运行时,如何获取完整的git push命令内容?

例如,当我 运行: git push origin master,执行预推挂钩。
我想在这个钩子中得到 origin & master

如何获取参数列表?

这些参数作为命令行参数传递给挂钩,您可以从那里获取它们。例如:

#!/bin/sh

remote=""
url=""

echo "remote:  ; url "

exit 0

那些参数被传递给钩子

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

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

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

# 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

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

您的挂钩脚本(假设 sh/bash)应包含以下形式的循环:

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

描述

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

开头

This hook is called by git push and can be used to prevent a push from taking place. The hook is called with two parameters which provide the name and location of the destination remote, if a named remote is not being used both values will be the same.

Information about what is to be pushed is provided on the hook’s standard input with lines of the form:

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

For instance, if the command git push origin master:foreign were run the hook would receive a line like the following:

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

although the full, 40-character SHA-1s would be supplied. ...

第一段表示在 shell 脚本中,</code> 和 <code> 是遥控器的名称——例如,origin——及其 URL,或者 URL 重复两次,如果用户 运行:

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

第二重要。一个git push命令可以推送多个b运行ch。例如,我可以 运行:

git push origin feature-A feature-B

同时推送 feature-A feature-B。您必须 阅读所有 输入行,一次一行,以发现要推送的内容。存储库中的 current b运行ch 并不重要:阅读 HEAD 会给你错误的答案 unless用户恰好在推送当前的 b运行ch。另一方面,大多数用户大多只是推送当前的 b运行ch。这会给你一种错觉,你的钩子是 100% 可靠的,而实际上它只有 92.37% 可靠。1

如文档所述,挂钩获取每个引用的全名。如果你推送 b运行ch,全名以 refs/heads/ 开头,但你可以推送标签,在这种情况下,全名以 refs/tags/ 开头。要编写可靠的钩子,您必须检查全名,而不是简单地剥离前两个部分。2


1像38.61%的统计​​,这个是现场编的。 :-)

2有很多糟糕的样本挂钩(并非所有都是预推挂钩)使用:

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

如果您正在推送标签 v2.3,此挂钩会认为您正在推送名为 v2.3b运行ch。如果你推的是一个名为 bugfix/1234 的 b运行ch,它会认为你推的是一个名为 bugfix 的 b运行ch! cut 技术是错误的,但后者的快速修复是使用 -f3-,它至少会产生 bugfix/1234。最好验证 ref 的第一个组件——即,做类似的事情:

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/}去掉已知的前缀,得到完整但不合格的b运行ch或标签名。但是,如果很多情况,您可以直接使用完整的参考名称。