在git“update”钩子中获取每个分支的提交

时间:2017-03-30 07:53:35

标签: git hook githooks

考虑创建所需git日志的下一个伪代码:

git checkout master
git checkout -b 123-test-branch-1
git commit -m "#123 b1 c1"
git commit -m "#123 b1 c2"
git push
git checkout master
git checkout -b 456-test-branch-2
git commit -m "#456 b2 c1"
git commit -m "#456 b2 c2"
git push
git checkout 123-test-branch-1
git merge 456-test-branch-2
git commit -m "#123 b1 c3"
git push

在现实世界中,远程git存储库中的update挂钩验证分支名称和提交消息格式。分支名称和提交消息必须包含问题编号,例如,在123-test-branch-1#123 b1 c1中,问题编号为123。当推送分支时,钩子从分支和提交消息中提取问题编号并进行比较。如果它们不相等,则挂钩会出错。

当我推送只有“拥有”提交的分支时,这很有用。但是,上面的git log示例,推送分支123-test-branch-1已经从合并分支456-test-branch-2提交,因此钩子尝试仅比较来自两个分支的所有提交与推送分支123-test-branch-1并且因为提交来自<{1}}的问题编号为456-test-branch-2,预计会456

要接收提交,我使用123,其中git log --pretty=%s ${oldRef}..${newRef}oldRef是“更新”挂钩参数。

所以,我的问题是如何解决这个问题。以某种方式对每个分支进行组提交,或者从现在推送的分支过滤提交(但如果newRef是本地分支并且从不推送且从未验证过,则钩子可能会跳过无效提交)或其他内容。

1 个答案:

答案 0 :(得分:1)

更新钩子没有获得足够的信息:它无法获得传入哈希ID的“全局视图”。接收前或接收后的钩子, 1 ,因此确实获得了足够的信息 - 至少出于某些目的。

最大的问题在于新的分支创建。例如,假设更新正在提供名称refs/heads/arefs/heads/b,其中两个名称都是新的(它们的旧哈希是空哈希),refs/heads/a指向提交{{1 }}和A指向此图片段中提交refs/heads/b

B

其中所有 N2 <-- A / ...--O--O--O--N1 \ N3 <-- B 提交都是“旧”(例如,之前可以从现有分支或标记名称访问)并且O提交是“新”,因为之前从未可以访问过,因此列于:

N

很明显,这三个git rev-list refs/heads/a refs/heads/b --not \ $(git for-each-ref --format '%(refname) | egrep -v '^(refs/heads/a|refs/heads/b)$') 提交是“新的”,但您应该指定哪个分支N

没有一个正确的答案。毕竟,提交N1在两个分支上。

在任何情况下,如果您更关心合并提交 - 例如:

N1

- 您可能想要使用...O1--O2--N1--N2 <-- A / ...-O3--O4--N3 <-- B 遍历。我们可以相信,基于这两个分支名称更新(--first-parentA移动到O2N2B移动到O4 }) - N3的第一个父级是N2(这可能,但很难,反过来使这种情况发生),所以跟随N1 s将“assign”commit { {1}}到--first-parent而不是N1。同样,如果您是从更新挂钩而不是接收前或接收后挂钩执行此操作,那么您可以做到最好,因为您没有获得两者的信息 {{建议更新1}} A

1 在删除所有锁之后运行post-receive钩子,因此它会对可能更新引用名称的其他操作进行竞争。预接收挂钩获取所有建议的更新,因此围绕引用名称更新存在很大的锁定,因此在某种意义上,在那里完成此工作显然更安全。

缺点是预接收钩子在握住一个大锁的同时运行,所以任何“慢”它都会阻止并行性。