当两个对等人同时将更改推送到同一个远程时,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首先处理他们的推送)首先到达那里,那么他们的推送将被接受,因为R
是T
的祖先,所以远程仓库也将具有历史P -- Q -- R -- T
如果你后来尝试推,你会得到一个错误,因为T
不是S
的祖先。 通常,看到这个! [rejected]
! [rejected]
错误,你要么运行git pull
或git pull --rebase
,以确保你在远程仓库中的主人之前。
git pull
将创build一个合并提交M
,使您的历史logging如下所示:
P -- Q -- R -- T -- M \ / -- S -
…而git pull --rebase
将重新应用您在T
之上引入的更改以创build新的提交, S'
:
P -- Q -- R -- T -- S'
在任何一种情况下,你都应该能够再次推动,因为T
是M
和S'
的祖先。 (这是假设没有其他人同时再次推!)
通过只允许快进,不需要解决远程冲突 – 如果有任何冲突,当你运行git pull
时候,你会被提示在本地解决它们。
值得注意的是,应用于远程仓库的更新响应推送是primefaces性的,所以在上面的例子中我们已经描述了S
和T
被同时推送的情况,其中一个是完全适用的,另一个是失败的,没有效果。
关于您的键/值存储点的说明
虽然Git的对象数据库被实现为键/值存储,它将对象名称(也称为散列或SHA1sums)映射到对象的内容,根据我的经验,学习Git的人很容易对Git的行为做出混淆的假设他们听到“这就像一个关键的价值存储” – 听起来好像这是可能发生在你的情况下,所以我build议在这个层面上考虑Git并不是解决这个问题最有用的方法。