鉴于您在裸存储库中使用钩子,您需要注意您从未真正比较两个分支。无论您对单词 branch 使用哪种定义,这都是正确的(请参阅What exactly do we mean by "branch"?)。您在这里与git diff-tree 真正比较的是两个提交。1
从根本上说,像master(实际上是refs/heads/master)或v2.1(实际上是refs/tags/v2.1)这样的名称只包含一个提交哈希ID。那是 a 哈希 ID,就像在一个单独的、单独的哈希 ID 中一样。请参阅链接问题,了解一个哈希 ID 如何表示多个提交。
像git diff 系列中的那些想要查看提交 的命令会将名称转换为原始哈希ID,然后像您输入原始哈希ID 一样继续操作。因此,如果你运行:
git rev-parse master
它会打印7c20df84bd21ec0215358381844274fa10515017,你可以在任何你写master的地方写下大而丑陋的哈希ID。 branch names 的特别之处在于它们移动,并且会自动移动——但是当您处于 pre-receive 和 post-receive 挂钩时,您必须格外小心这是因为他们移动的时间很棘手。这就是为什么你应该使用这样的循环:
while read oldrev newrev ref; do ...; done
这些循环读取三个项目:两个哈希 ID 和一个完整的参考名称。这两个哈希 ID 是引用的 previous 值(过去是完整引用名称解析的哈希值)和 new 值,即引用的哈希 ID参考将很快代表。最后一项是全名:refs/heads/master、refs/tags/v2.1,以此类推。名字的前面部分告诉你它是什么种类,名字的其余部分,在去掉前面部分后,是分支或标签或其他名字。
在 pre-receive 或 update 钩子中,名称本身还没有改变,所以名称应该解析为旧的哈希。你的钩子的工作是验证这些提议的更新是否应该被允许。在 post-receive 挂钩中,名称本身已更改。您应该使用散列 ID,而不是现在将名称解析为散列 ID,因为 另一个 更改可能正在等待或已经发生,这取决于您的接收后挂钩本身有多慢。
您在预接收或更新挂钩中生成的任何输出都将被复制到执行触发挂钩运行的git push 操作的任何人。 (此输出将以单词remote: 为前缀,并且在您发送完整行之前不会出现。)您在接收后挂钩中生成的任何输出都将被丢弃!如果您希望将其保存在服务器上,则必须将其发送到日志文件或日志服务或类似服务。
不需要--work-tree 参数(使用一个参数可能不明智),但您可能需要在预接收或更新挂钩中完成工作,并酌情使用原始哈希 ID。是否要更新 refs/heads/master 和 refs/heads/develop 的值由您决定,是否建议更新这两个名称。如果 既不 refs/heads/master 也不 refs/heads/develop 建议更新,是否打印 git diff-tree 的结果也取决于您。
1您可以直接比较树,git diff-tree 的形式可以产生多于两棵树的组合差异,但在这里使用master develop '非常清楚地选择了master 和develop 的提示提交。