我是git的新手,我通常使用具有中央存储库的P4,而git是分布式VCS。
我感兴趣的是当两个对等体同时向同一个遥控器推送更改时git如何工作。 假设每个对等体在推送之前解决了所有冲突。我想如果git报告冲突,后者将被拒绝!
但是,据我所知,git在内部是一个键/值存储,就像当前流行的NOSQL数据库,尤其是支持p2p复制的Couch-DB。
实际上我想问一下,在客户端将更改推送到远程git存储库的情况下,git进程如何冲突?推被拒绝了吗?
从Mark的回答中,我认为应该拒绝推动。
答案 0 :(得分:66)
是的,其中一个推动将被拒绝 - 无论哪个推迟,即使只是一微秒,正如Jefromi在他的评论中提到的那样。但是,它将被拒绝,因为远程存储库看到后一个推送的历史记录不包括前一个推送的历史记录,而不是因为它看到正在推送的内容中的任何冲突。
如果在Git术语中它不会“快进”分支,通常会拒绝推送。这意味着如果您的主人位于A且远程存储库位于B,那么只有当B是A的祖先时才推送。(我说“通常”因为您可以添加选项以“强制”推送,如果远程存储库允许这样做,但这不是典型的情况。)
在您描述的情况下,假设所有三个存储库最初具有相同的历史记录:
P -- Q -- R
你添加了一个提交S:
P -- Q -- R -- S
...而其他人添加了提交T:
P -- Q -- R -- T
如果其他人在推送时首先到达那里(也就是说,服务器上的Git首先处理他们的推送),那么他们的推送将被接受,因为R
是T
的祖先,所以然后,远程存储库也将具有历史记录P -- Q -- R -- T
。如果您随后尝试推送,则会收到错误,因为T
不是S
的祖先。通常,在看到! [rejected]
错误时,您将运行git pull
或git pull --rebase
以确保您在远程存储库中位于master之前。
git pull
将创建合并提交M
,以使您的历史记录如下:
P -- Q -- R -- T -- M
\ /
-- S -
... git pull --rebase
将重新应用您在T
之上引入的更改,以创建新提交S'
:
P -- Q -- R -- T -- S'
在其中任何一种情况下,您都应该能够再次推送,因为T
是M
和S'
的祖先。 (假设没有其他人在同一时间再推!)
只允许快进,永远不必解决远程冲突 - 如果有任何冲突,当您运行git pull
时,系统会提示您在本地解决冲突。
值得注意的是,响应推送而应用于远程存储库的更新是原子的,因此在我们上面描述的示例情况中,S
和T
被推送到同时,总是是其中一个完全应用而另一个失败,没有效果的情况。
关于您的键/值存储点的说明
虽然Git的对象数据库是作为键/值存储实现的,它将对象名称(也称为哈希或SHA1sums)映射到对象的内容,但根据我的经验,人们学习Git很容易对如何做出令人困惑的假设Git在听到“它就像一个关键值存储”时表现得很好 - 听起来好像这可能发生在你的情况下,所以我建议在这个级别考虑Git并不是理解这个问题的最有用的方法。