【发布时间】:2017-07-16 06:44:48
【问题描述】:
当一个 Git pre-push hooks 脚本运行时,如何获取完整的git push 命令内容?
例如,当我运行:git push origin master 时,执行了预推送挂钩。
我想在这个钩子里得到origin & master。
如何获取参数列表?
【问题讨论】:
标签: git shell githooks git-push
当一个 Git pre-push hooks 脚本运行时,如何获取完整的git push 命令内容?
例如,当我运行:git push origin master 时,执行了预推送挂钩。
我想在这个钩子里得到origin & master。
如何获取参数列表?
【问题讨论】:
标签: git shell githooks git-push
您的钩子脚本(假设为 sh/bash)应包含以下形式的循环:
while read localname localhash remotename remotehash; do
... code here using $localname etc ...
done
the githooks page 中描述了所有 Git 挂钩。 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 会给你错误的答案除非用户碰巧正在推送当前分支。另一方面,大多数用户大多只是推送当前分支。这会让您产生一种错觉,即您的 hook 是 100% 可靠的,而实际上只有 92.37% 可靠。1
如文档所述,钩子获取每个引用的全名。如果您正在推送一个分支,则该全名以refs/heads/ 开头,但您可以推送一个标签,在这种情况下,全名以refs/tags/ 开头。要编写可靠的钩子,您必须检查全名,而不是简单地剥离前两个组件。2
1和 38.61% 的统计数据一样,这个是当场编造的。 :-)
2有很多不好的示例钩子(不是所有的 pre-push 钩子)都在使用:
branch=$(echo $ref | cut -d/ -f3)
如果你正在推送标签v2.3,这个钩子会认为你正在推送一个名为v2.3 的分支。如果你正在推送一个名为bugfix/1234 的分支,它会认为你正在推送一个名为bugfix 的分支! 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/} 去除已知前缀并获得完整但不合格的分支或标记名称。但是,如果在很多情况下,您可以直接使用完整的参考名称。
【讨论】:
这些参数作为命令行参数传递给钩子,您可以从那里获取它们。例如:
#!/bin/sh
remote="$1"
url="$2"
echo "remote: $1 ; url $2"
exit 0
【讨论】:
这些参数被传递给钩子
在钩子中你可以得到这样的分支名称:
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
【讨论】:
git status -b --short 而不是git status -b --porcelain。如果您启用了color.status 配置(默认),它会以更易读的方式提供相同的信息。 porcelain 选项默认禁用颜色。
--porcelain 用于脚本,其中颜色会妨碍脚本解释输出。 --short 用于人类消费,除非您是色盲,否则颜色很有用:-)
/,您的sed 咒语将返回错误结果。最好使用git rev-parse --abbrev-ref HEAD 直接获取当前分支名称(不带refs/heads 前缀),避免进行此类操作。