集中合并所有提交

Merging all the commits centrally

为简化情况假设两个用户的提交历史如下

A -> B -> C     A -> B -> D  # and Repo at  A -> B

并且两个用户都尝试在同时推送。第一个用户将首先获得机会,现在回购在

A -> B -> C

现在第二个用户必须在推之前再次拉,所以他现在在

A -> B -> C -> D or A -> B -> D -> C

所以这首先提出了两个问题,这个合并是如何发生的(在时间戳上..!)? git 如何决定哪些提交先 C 或 D。其次是为什么不能在远程或中央 Repo 执行此合并操作。(假设没有合并冲突)?

我正在考虑将 git 用于其他一些 同步 技术 所以假设有 N 个用户试图同时推送某些内容,那么每个用户都必须在能够推动之前拉 N-1 次。

所以假设没有合并冲突,有没有办法集中执行合并。只是为了澄清用户最终会拉动,但我只是想避免 N-1 拉动。

each user will have to pull N-1 times before being able to push

他们不会:每个用户将拉然后再次尝试推送。如果在此期间没有其他用户推送,则一次拉取将成功。
必须拉 n-1 次(意味着每次推送失败,因为另一个用户刚刚推送)的机会非常低。

don't you think it can be a major issue in practice if 100 user trying to push at the same time and last 1 will have to pull 99 time before being able to push.?

不,因为如果在那种情况下,您可以通过允许每个用户推送到专用分支(每个用户一个)来避免该问题。
这样的并发操作将在服务器端解决(合并在集成分支中完成)。它不会留给客户端(你所描述的太麻烦而无法解决)

what about using queuing system (rabbitmq probably) to transfer all git objects to a bare repo and setting the head as required. what is your thought on it. would it be nice in clustering situation?

您需要确保传输不会失败(因此每个用户一个分支)
然后,在那个裸 git 仓库上,另一个进程可以尝试合并任何推送到用户分支的新提交。如果由于冲突而失败,它会发送一封通知电子邮件,让集成商解决问题。

如果你的N个用户都是机器,而且都运行速度一样,那么是的,你就会有这个问题。

但实际上,让我们只用四个演员来查看这个问题,看看他们中的三个是否真的有这个问题。我们的四位选手是 Carol、David、Emma 和 Fallon。

中央存储库以提交 A 和 B 开始,如您的示例所示。不知何故,Carol、David、Emma 和 Fallon 这四个人同时完成了他们的新提交,并且都以 14:17:23.2 的速度推送,但是 Carol 的计算机是最快的,所以她的提交进入了中央存储库:

A--B--C   <-- master

David、Emma 和 Fallon 收到一条错误消息,告诉他们他们的推送不是快进的,他们必须重试。但是 Fallon 的 phone 正在响铃(或带有短信的嗡嗡声)所以他因此分心了。与此同时,David 和 Emma 都注意到他们的推送失败了。

David 以前没有见过这个,所以他现在必须去搜索 Whosebug 看看他应该做什么。 Emma比较熟悉Git;她 运行s git fetch && git rebase && git show 并且看到她的改变很好。现在是 14:18:09.6。艾玛输入 git push origin master,她的推送通过:

A--B--C--E

David 现在正在阅读有关合并与变基的内容。 Fallon 或多或少在 14:19:39 处从 phone 下车,并注意到故障。 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 领先一点,所以他的推进成功了,David 又犯了一个 "non-fast-forward" 错误。中央存储库现在镜像 Fallon 的存储库:

A--B--C--E--G   <-- master
    \      /
     F----/

David 当然也读到了 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 时成功。中央存储库在 master 上获得提交 D',每个人都很高兴。

大卫是唯一一个两次去取的人,整个过程大约用了四分钟。当然他还不明白 git pull 到底是怎么工作的,但至少他现在知道使用 rebase 了。 :-)