我正在研究在中央SCM服务器端实施“预提交”验证流程的可能性。在本段中,“预提交”并不是指git挂钩,而是指在更改成为集成分支的一部分之前,该分支上的所有开发人员都可以看到。特别是pre-commit(它是分布式SCM),git阶段发生在本地服务器上,这不是我所需要的。所以我不能使用commit git挂钩。

从我那里收集到的pre-commit钩子就是我想要的东西:存储库,
在本地存储库上执行“ git push”时发生。在开始更新远程存储库上的引用之前,
会调用预接收钩子。它的退出状态确定更新成功与否。

该挂钩对接收操作执行一次。 [snip]

如果挂钩以非零状态退出,则所有引用均不会更新。如果钩子以零退出,则仍然可以通过pre-receive钩子来阻止单个引用的更新。 >
该挂钩由远程存储库上的“ git-receive-pack”调用,
在本地存储库上执行“ git push”时发生。只是
,在更新远程存储库上的引用之前,将调用更新挂钩。它的退出状态决定了ref
更新的成功与否。

该挂钩对每个要更新的ref执行一次, >问题是验证本身可能需要一段时间。

我的问题:这些挂钩的执行是否已序列化(通过<<update,'update'>>进行)?含义将是另一个钩子调用(由于在先前的钩子执行完成之前执行了后续的update操作):


失败,
阻塞直到前一个仍在运行的执行完成,




与上一个钩子执行并行运行?


#1 楼

一般来说,git允许并发操作,因为其中之一最终会失败。一些特定的数据库更新将具有文件锁(例如更新索引文件),但我认为一次可以进行多个接收。在这种情况下,无论哪个操作都将首先完成,而第二次操作将由于历史记录无效(即不是快进推送)而失败。非常适合git的服务器端挂钩,因为如果某些操作确实失败,那么该人将不得不对其分支机构进行一些手术以使事情恢复到有效状态。这些检查通常在工作站端运行,但是随后您会遇到分发git hook的“乐趣”,因为它们实际上无法直接检入。拥有像Jenkins这样的CI服务,可以运行验证(测试)并更新第二个分支或实用工具标签,以显示可接受的提交。

评论


是的,这证实了我的怀疑-正是我所担心的。而且这两个建议(私有开发人员验证和提交后的CI验证)都有缺点,这些缺点是大规模集成的严重障碍-这是我首先要解决的问题:)需要更多的思考。

–丹·科尼莱斯库(Dan Cornilescu)
17 Mar 8 '17 at 18:09

#2 楼

当运行特定的Git命令时,将执行每个Git挂钩。有关详细信息,请参见钩子上的Git文档。如果您有两次推送更新相同的引用,则其中一个完成“ update”钩子的操作将首先更新该引用,而另一个将获得错误。哪个客户端首先开始无关紧要。这是所有必须首先更新ref的问题。

发生推送时,这会运行许多钩子。这三个程序在可以更新引用之前运行。


pre-push-客户端,由git push调用,可用于防止进行推送。
pre-receive-服务器端,由远程存储库上的git-receive-pack调用。在开始更新远程存储库上的引用之前,将调用pre-receive钩子。其退出状态确定更新的成功或失败。如果挂钩以非零状态退出,则不会更新任何引用。如果钩子以零退出,则仍然可以通过update钩子来阻止单个引用的更新。
update-服务器端,由远程存储库上的git-receive-pack调用。在更新远程存储库上的引用之前,将调用更新挂钩。其退出状态确定引用更新的成功或失败。该挂钩对每个要更新的引用执行一次。

我的2分:我认为您是在问一个错误的问题。任何使用Git钩子的操作都应该快速简单。如果您的验证需要一秒或两秒以上的时间,则该时间太长,可能会被放到Git挂钩中。长时间运行的钩子会使用户感到沮丧,因为他们会认为Git没有响应。我的建议是应用FAIL FAST,FAIL OFTEN原则。

对于长期运行的验证,最好使用工具在Git之外进行验证,例如可以从CI或本地运行的单元测试。正确使用请求请求(即合并短暂的分支)应该检查您的验证是否通过,然后允许合并这样的更改。

评论


如果可以并行执行多个验证服务器,则长时间运行的验证服务器端可能会被接受,如果验证正常,则所有验证都将成功。但这并没有发生,因此不能将其用作快捷方式-退回到客户端的仅候选人提交以及服务器端的自动提交。接下来检查git format-patch工作流程:)

–丹·科尼莱斯库(Dan Cornilescu)
17 Mar 8 '17 at 23:32