tor*_*rek 10
cmaster的回答是正确的,有警告.让我们首先注意这些项目/假设:
--ours
)和R表示右/远程(--theirs
).第一个假设不一定正确.如果有多个合并基础候选者,则由合并策略决定对此做些什么.两个标准的双头合并策略是recursive
和resolve
.该resolve
策略只选择(明显)随机选择一个.该recursive
策略一次合并两个合并库,然后使用生成的提交作为合并库.被选择的一个resolve
可以通过参数的顺序影响git merge-base
,因此对git merge
,所以这是一个警告就在那里.因为递归策略可以进行多个合并,所以这里有一个很难描述的第二个警告,但只有在有两个以上的合并基础时它才适用.
第二个假设更为正确,但请注意,合并代码可以在部分修改的工作树上运行.在这种情况下,所有投注均已关闭,因为工作树与L或R不匹配.标准git merge
会告诉你必须先提交,所以通常这不是问题.
我们已经注意到多个合并基础的问题.我们假设还有一个双头合并.
八达通合并可以处理多个头.这也改变了合并基础计算,但总的来说章鱼合并不适用于具有复杂合并问题的情况,并且只是拒绝在订单可能重要的地方运行.不过,我不会强调它; 这是对称规则可能失败的另一种情况.
该-s ours
合并策略完全忽略其他所有提交这样合并顺序显然是至关重要的位置:结果始终是大号.(我很确定-s ours
甚至不打算计算合并基数B.)
你可以编写自己的策略并做任何你想做的事情.在这里,您可以使订单重要,就像它一样-s ours
.
Git现在实际上计算了这三个快照中的两个变更集:
git diff --find-renames B L
git diff --find-renames B R
这里的重命名探测器是独立的 - 我的意思是既不影响另一个; 两者都使用相同的规则.这里的主要问题是,B中的同一个文件可能被检测为在两个变更集中重命名,在这种情况下,我们得到了所谓的高级冲突,特别是重命名/重命名冲突.(我们也可以通过重命名/删除和其他几种情况获得高级冲突.)对于重命名/重命名冲突,Git选择的最终名称是L中的名称,而不是R中的名称.所以在这里,顺序就最终文件名而言很重要.这不会影响工作树合并内容.
在这一点上,我们应该参观一下Git的内部.我们现在在B -vs- L和B -vs- R中配对文件,即,我们知道哪三个提交中的哪些文件是"相同"文件.但是,Git存储文件和提交的方式很有趣.从逻辑上看,Git 没有增量:每个提交都是所有文件的完整快照.每个文件,然而,仅仅是一个实体对:一路径名P和散列ID ħ.
换句话说,此时,不需要遍历从B到L或R的所有提交.我们知道我们有一些文件F,最多由三个独立的路径名识别(如上所述,Git 在大多数情况下将使用L路径,但如果B -v中只有一个重命名,则使用R路径 - R侧合并).通过直接查找可以获得所有三个文件的完整内容:H B表示基本文件内容,H L表示左侧文件,H R表示右侧文件.
当且仅当它们的哈希值匹配时,两个文件才完全匹配.1 因此,此时Git只是比较哈希ID.如果所有三个匹配,则合并的文件与左右文件和基本文件相同:没有工作.如果L和R匹配,则合并文件是L或R内容; 由于双方做出了同样的改变,基地无关紧要.如果B匹配L或R但不匹配另一个,则合并文件是不匹配的散列.如果存在潜在的低级合并冲突,Git只需要进行低级合并.
所以现在,Git提取三个内容并进行合并.这是逐行工作的(当多个相邻行被更改时,行组合在一起):
如果左侧和右侧仅触及不同的源线,Git将进行两次更改.这显然是对称的.
如果左右触摸相同的源行,Git将检查更改本身是否也相同.如果是这样,Git将获取一份更改.这也是对称的.
如果左右触摸相同的行,但做了不同的更改,Git将声明合并冲突.工作树内容将取决于更改的顺序,因为工作树内容具有<<<<<<< HEAD ... ||||||| base ... ======= ... other >>>>>>>
标记(该base
部分是可选的,如果选择diff3
样式则显示).
相同行的定义有点棘手.这取决于diff算法(您可以选择),因为某些文件的某些部分可能会重复.但是,Git总是使用单个算法来计算L和R,所以这里的顺序并不重要.
1换句话说,如果你设法生成一个Doppelgänger文件 - 一个与一些现有文件具有不同内容,但具有相同哈希值的文件,Git只是拒绝将该文件放入存储库.shattered.it PDF不是这样的文件,因为Git用文件的blob
大小和文件的大小作为文件数据的前缀,但原则适用. 请注意,将这样的文件放入SVN会破坏SVN.
您可以使用-X ours
或覆盖合并冲突投诉-X theirs
.这些直接Git分别解决了有利于L或R变化的冲突.
即使有上述警告,这种对称原理也适用于单一合并.但是一旦进行了合并,您运行的下一个合并将使用修改后的提交图来计算新的合并基础.如果您打算进行两次合并,则执行以下操作:
git merge one (and fix conflicts and commit if needed)
git merge two (fix conflicts and commit if needed)
Run Code Online (Sandbox Code Playgroud)
那么即使每个合并中的所有内容都是对称的,这并不意味着您必须获得与运行时相同的结果:
git merge two
git merge one
Run Code Online (Sandbox Code Playgroud)
无论哪个合并首先运行,您都会获得合并提交,第二个合并现在会找到不同的合并基础.
如果确实存在必须在完成合并之前必须修复的冲突,这一点尤其重要,因为这也会影响第二个命令的L输入git merge
.它将使用第一个合并的快照作为L,并将新的(可能不同的)合并基础作为B,用于其三个输入中的两个.
这就是为什么我提到-s recursive
在使用多个合并库时可能存在顺序差异的原因.假设有三个合并基础.Git将合并前两个(以它们弹出合并基础计算的顺序),提交结果(即使存在合并冲突 - 它只是在这种情况下提交冲突),然后将该提交与第三个提交合并并提交结果.最后提交这里是那么输入乙.只有当此过程的所有部分都是对称的时,最终的B结果才会对顺序不敏感. 大多数合并是对称的,但我们看到了上面的所有警告.
归档时间: |
|
查看次数: |
1933 次 |
最近记录: |