考虑创建所需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
是本地分支并且从不推送且从未验证过,则钩子可能会跳过无效提交)或其他内容。
答案 0 :(得分:1)
更新钩子没有获得足够的信息:它无法获得传入哈希ID的“全局视图”。接收前或接收后的钩子, 1 ,因此确实获得了足够的信息 - 至少出于某些目的。
最大的问题在于新的分支创建。例如,假设更新正在提供名称refs/heads/a
和refs/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-parent
从A
移动到O2
,N2
从B
移动到O4
}) - N3
的第一个父级是N2
(这可能,但很难,反过来使这种情况发生),所以跟随N1
s将“assign”commit { {1}}到--first-parent
而不是N1
。同样,如果您是从更新挂钩而不是接收前或接收后挂钩执行此操作,那么您可以做到最好,因为您没有获得两者的信息 {{建议更新1}} 和 A
。
1 在删除所有锁之后运行post-receive钩子,因此它会对可能更新引用名称的其他操作进行竞争。预接收挂钩获取所有建议的更新,因此围绕引用名称更新存在很大的锁定,因此在某种意义上,在那里完成此工作显然更安全。
缺点是预接收钩子在握住一个大锁的同时运行,所以任何“慢”它都会阻止并行性。