为了简化这种情况,假设两个用户提交历史记录就像
A -> B -> C A -> B -> D # and Repo at A -> B
并且两个用户都尝试按同时推送。第一个用户将首先获得机会,现在回购是
A -> B -> C
现在第二个用户必须在推动之前再次拉动,所以他现在在
A -> B -> C -> D or A -> B -> D -> C
所以这首先提出两个问题是这个Merge是如何发生的(在时间戳上......!)? git如何决定哪个提交首先出现在C或D中。第二个是为什么这个合并的东西不能在Remote或Central Repo上执行。(假设没有合并冲突)?
我正在考虑将git用于其他同步技术所以假设有N个用户同时尝试推送某个东西,那么每个用户必须先拉N-1次才能推。
因此,假设没有合并冲突,有一种方法可以集中执行合并。只是为了澄清用户最终会拉,但我只想避免N-1拉动。
答案 0 :(得分:2)
每个用户在推送
之前必须拉N-1次
他们不会:每个用户都会拉,然后再次尝试推送。如果另一个用户没有推进,那么一次拉动就会成功 必须拉n-1次的机会(意味着每次推动失败,因为另一个用户刚刚推动)非常低。
难道你不认为这可能是一个重大问题,如果100个用户试图同时推送而且持续1次将需要拉99次才能推送。
不,因为如果在这种情况下,您可以通过允许每个用户进入专用分支(每个用户一个)来避免该问题。
这样的并发操作将在服务器端解决(在集成分支中完成合并)。它不会留给客户端(你所描述的内容太难解决)
如何使用排队系统(可能是rabbitmq)将所有git对象转移到一个裸仓库并根据需要设置头部。你对它的想法是什么?在聚类情况下会不会很好?
您需要确保转移不会失败(因此每个用户一个分支)
然后,在那个裸git repo上,另一个进程可以尝试合并任何推送到用户分支的新提交。如果由于冲突而失败,它将发送通知电子邮件给集成商以解决这种情况。
答案 1 :(得分:2)
如果您的N个用户是机器,并且所有用户都以相同的速度运行,那么是的,您将遇到此问题。
但实际上,让我们只用四个演员来看问题,看看其中三个是否真的有这个问题。我们的四名球员是Carol,David,Emma和Fallon。
中央存储库以提交A和B开头,如您的示例所示。不知何故,卡罗尔,大卫,艾玛和法伦四个人同时完成了他们的新提交,所有人都在14:17:23.2推进,但卡罗尔的计算机是最快的,所以她的提交进入中央存储库:
A--B--C <-- master
David,Emma和Fallon收到一条错误消息,告诉他们他们的推送不是快进的,他们必须重试。但法伦的手机响了(或者是文字嗡嗡声),所以他会分心。与此同时,大卫和艾玛都注意到他们的推动失败了。
大卫以前没见过这个,所以他现在必须去搜索StackOverflow才能看到他应该做的事情。艾玛对Git比较熟悉;她跑git fetch && git rebase && git show
,发现她的变化很好。现在是14:18:09.6。 git push origin master
中的艾玛类型和她的推动经历了:
A--B--C--E
David现在正在阅读有关合并与rebase的内容。法伦在14:19:39或多或少地下电,并注意到失败。 David和Fallon都跑git pull
(他们不像Emma聪明,也没有意识到rebase更好);他们的存储库变成了:
A--B--C--E--M <-- master
\ /
D----/
和
A--B--C--E--G <-- master
\ /
F----/
分别。通过一些奇迹,他们几乎同时推进,14:21:01-and-a-fraction,Fallon有点领先,所以他的推动经历了大卫得到另一个“非快进”错误。中央存储库现在镜像了Fallon的存储库:
A--B--C--E--G <-- master
\ /
F----/
当然,大卫也读过关于rebase的内容,所以他试着git pull --rebase
,认为它与git pull
有点神奇不同(当它真正做到的只是git fetch && git rebase
的道德等价时而不是git fetch && git merge
)。这会将其提交D
复制到G
:的末尾
A--B--C--E--G--D' <-- master
|\ /
| F----/
\
D [abandoned]
他再次尝试git push
并在14:21:28成功。中央存储库在D'
上获得提交master
,每个人都很高兴。
大卫是唯一一个不得不取两次的人,整个过程大约需要四分钟。当然他仍然不明白git pull
如何真正起作用,但至少他现在知道使用rebase。 : - )