当两个对等人同时将更改推送到同一个远程时,git如何工作

我是git的新手,我通常使用有中心存储库的P4,而git是分布式的VCS。

我感兴趣的是两个同伴如何同时将更改推送到同一个远程,git是如何工作的。 假设每个对等方在推送之前解决所有冲突。 我想如果git报告冲突,后面的一个会被拒绝!

然而,据我所知,git在内部是一个键/值存储,就像当前stream行的NOSQL数据库,尤其是支持p2p复制的Couch-DB。

其实我想问一下,在客户端将更改推送到远程git存储库的情况下,git进程如何冲突呢? 推送被拒绝了吗?

从马克的回答中,我认为推动应该被拒绝。

简短的回答

是的,正如Jefromi在评论中提到的那样,其中一个推动将被拒绝 – 无论哪个稍后,哪怕只有微秒。 但是,它将被拒绝,因为远程存储库认为后面的推送的历史不包括较早推送的历史,而不是因为它看到正在推送的内容中的任何冲突。

更详细的答案

通常情况下,推送将被拒绝,如果它不会“快进”的分支,在Git术语。 这意味着如果你的主人在A,而远程仓库在B,那么只有当B是A的祖先时,推才会成功。(我说“通常”是因为你可以添加选项来“强制”远程存储库允许,但这不是典型的情况。)

在你描述的情况下,假设所有三个存储库最初都有相同的历史logging:

P -- Q -- R 

你已经添加了一个提交S:

 P -- Q -- R -- S 

…而其他人已经添加了一个提交T:

 P -- Q -- R -- T 

如果其他人在推送时(即,服务器上的Git首先处理他们的推送)首先到达那里,那么他们的推送将被接受,因为RT的祖先,所以远程仓库也将具有历史P -- Q -- R -- T 如果你后来尝试推,你会得到一个错误,因为T不是S的祖先。 通常,看到这个! [rejected] ! [rejected]错误,你要么运行git pullgit pull --rebase ,以确保你在远程仓库中的主人之前。

git pull将创build一个合并提交M ,使您的历史logging如下所示:

 P -- Q -- R -- T -- M \ / -- S - 

…而git pull --rebase将重新应用您在T之上引入的更改以创build新的提交, S'

 P -- Q -- R -- T -- S' 

在任何一种情况下,你都应该能够再次推动,因为TMS'的祖先。 (这是假设没有其他人同时再次推!)

通过只允许快进,不需要解决远程冲突 – 如果有任何冲突,当你运行git pull时候,你会被提示在本地解决它们。

值得注意的是,应用于远程仓库的更新响应推送是primefaces性的,所以在上面的例子中我们已经描述了ST被同时推送的情况,其中一个是完全适用的,另一个是失败的,没有效果。

关于您的键/值存储点的说明

虽然Git的对象数据库被实现为键/值存储,它将对象名称(也称为散列或SHA1sums)映射到对象的内容,根据我的经验,学习Git的人很容易对Git的行为做出混淆的假设他们听到“这就像一个关键的价值存储” – 听起来好像这是可能发生在你的情况下,所以我build议在这个层面上考虑Git并不是解决这个问题最有用的方法。