如果第二次推送只有第一次推送的快进,那么并发git推送是否总是安全的?

时间:2011-12-07 22:00:48

标签: git concurrency backup automated-tests git-post-receive

我想自动将后接收挂钩中的提交从LAN上的中央仓库推送到云中的另一个中央仓库。 LAN repo使用git clone --mirror git@cloud:/path/to/repo或等效命令创建。

因为提交的文件相对于我们的上游带宽会很大,所以完全有可能发生这样的事情:

  1. Alice启动了对局域网仓库的推送。
  2. 当收件后挂钩正在运行时,Bill从LAN repo中拉出来。
    • LAN repo正在推动云回购。
    • 这也意味着Bill的本地存储包含Alice推送的提交。通过测试确认。
  3. Bill开始推动局域网回购。
    • 比尔的推动是爱丽丝推进的快速推进,因此局域网回购将接受它。
  4. 当LAN repo的post-receive挂钩执行时,将从LAN repo到cloud repo的第二次推送开始,两者将同时运行。

    我并不担心git对象。最糟糕的情况是,两者都推送上传所有对象来自Alice的推送,但就我理解git的内部而言,这并不重要。

    我关注裁判。 假设Alice推送使用更慢的连接,以便Bill推送完成。假设数据包丢失或其他原因导致挂钩从LAN repo推送到Bill&的云端在从局域网回购推送到爱丽丝的推送云之前,推动完成。如果Alice和Bill都在推动主分支并且Bill的推送首先完成,那么主要参与者将在云回购中做什么?我希望它成为比尔的头,因为这是后来的推动,但我担心这将是爱丽丝的头。

    进一步澄清:

    我意识到,如果比尔从他的机器推送到局域网回购首先完成,那么爱丽丝从她的机器推送到局域网回购将会失败。在这种情况下,LAN repo的接收后挂钩将不会执行。此外,请假设没有人会进行强制推送,所以如果在LAN回购上运行后接收挂钩,则所有参考更改都是快进的。

2 个答案:

答案 0 :(得分:4)

如果Bill的推送完成,那么Alice的推送会失败,因为在更新ref之前,git会确保repo的ref仍然与以前相同。在这种情况下,它不会。 Alice最终会看到错误消息并需要解决问题。比尔在反之亦然的情况下也是如此。所以在你的post-receive钩子中你必须确保repo的原始和新refs现在不同。如果没有,那么根本不要推到新的仓库以节省一些工作。

我仍然在你的场景中看到了一个问题,而且是在推送到云端。您可以通过钩子将两个有效引用推送到云位置时出现相同问题。除非你现在不知道你是否需要在脚本中推送到repo,如果它第一次失败,因为你不知道失败的ref是旧的还是比推的更新...特别是如果他们不是&# 39;简单的快进,可能会不时发生。如果你只是强迫推送无论什么东西都有可能云将有一个旧的参考,直到另一个钩子推动其他东西后来。在Alice的情况下,他会合并来自上游或任何其他解决方案的更改,但脚本可能不应该具有这样的决策能力。

在钩子中,您可以在当前仓库上执行一些脚本魔术以确定时间戳等,并且只有在快进时才会推送,但这看起来很混乱,并且更有可能需要合并。我认为比使用post-receive钩子更好的解决方案是每隔五分钟(或者你想要的频率)使用cron或者预定的任务,只需在远程镜像的主分支上运行git pull。如果您无权访问该回购,则可以使用cron作业从LAN回购执行强制推送。我认为这比钩子更安全,而且不那么复杂。这将确保备份云上的分支每隔几分钟始终处于正确的位置,并且不会冒险推送旧的ref并且永远不会获得最新的ref,直到有来自用户的另一次推送,如钩子那样。

答案 1 :(得分:1)

Git 2.4+ (Q2 2015)将引入原子推送,这将使服务器更容易管理推送订单。
查看Stefan Beller (stefanbeller)所做的工作:

  • commit ad35eca t5543-atomic-push.sh:添加原子推送的基本测试
  

这增加了原子推送选项的测试   前四个测试检查原子选项是否在良好的条件下工作,最后三个补丁检查原子选项是否阻止在只有一个ref无法更新时推送任何更改。

  

如果可用,请在远程端使用原子事务   要么更新所有引用,要么出错,不更新引用   如果服务器不支持原子推送,则推送将失败。

  

这增加了对send-pack的支持,以协商和使用原子推送   iff服务器支持它。原子推送由新命令激活   line flag --atomic

  

这会将原子协议选项添加到允许receive-pack通知客户端它具有原子推送功能
  此提交使先前提交中引入的功能在服务端生效   文档中的更改反映了服务器的协议功能。

   atomic
   ------
  

如果服务器发送了' atomic'能够接受原子推动的能力   如果推送客户端请求此功能,则服务器将在一个原子事务中更新ref   要么更新所有引用,要么都不更新。