存在两个存储库:rep1,rep2。两者都是来自同一SVN实例的单向同步的结果。 (SVN中的更改与git同步,但git中的更改未同步回SVN)两个存储库不是彼此的分支。
rep1 / master分支包含文件file1.txt
rep2 / master分支包含文件file1.txt,但该文件已在rep2 /中删除
rep2在rep1中作为远程添加,以便合并。 (remot2)
分支rep2 / master已创建
git checkout -b rep2_master_branch --track rep2/master
从rep1 / master的tip创建“merge”分支
git checkout -b merge-master-branches master
使用选项“他们的”和壁球执行合并。由于合并来自另一台服务器,因此需要不相关的历史记录。
git merge -Xtheirs --squash rep2_master_branch --allow-unrelated-histories
观察到的是不删除rep1 / file1.txt。
进一步观察,合并期间的冲突得到正确解决,修改和添加文件也是如此。似乎唯一的遗漏是在rep2中删除的文件。
我该如何解决这个问题?或者更好的是,如何解决这个问题?
就Git而言,这是正确的合并结果。
Git的git merge
通过将两个分支提示与一个公共合并基础进行比较来实现。也就是说,如果你绘制提交图,它看起来像这样:
o--o--L <-- branch1
/
...--o--o--*
\
o--o--R <-- branch2
那么将branch1
(commit L
)与branch2
(commit R
)合并的结果将通过比较commit *
(两个分支派生的公共点)的内容与commit L
的内容和commit R
的内容进行比较来计算。
无论从*
到L
的变化都发生在左侧。无论从*
到R
的变化发生在右侧。 Git结合了这两个“发生的事情”,将这些组合的变化应用于*
的内容,如果一切顺利,则从结果中进行新的提交。
但你正在使用--allow-unrelated-histories
。只有在没有共同提交时才需要这样做:我们绘制L
和R
的历史,并发现它们从不偏离共同点。例如,我们可能会得到:
A--o--o--...--L <-- branch1
B--o--...--o--R <-- branch2
其中A
和B
都是root提交。那么Git应该用什么作为共同的起点,弄清楚从那以后发生了什么变化?
人们可以争论一个人选择的各种起点,但Git的答案是:使用空提交。也就是说,使用--allow-unrelated-histories
,Git假装有一个没有文件的常见提交:
A--o--o--...--L <-- branch1
/
*
\
B--o--...--o--R <-- branch2
将提交*
(为空)与提交L
进行比较,Git发现branch1
上的每个文件都是以L
中的形式新创建的。比较*
和R
,Git发现branch2
上的每个文件都是以R
中的形式新创建的。无论这些文件匹配在哪里,一切都很好:我们只需要获取该文件。无论L
有R
没有的文件,反之亦然,一切都很好:我们只拿这个文件。无论L
和R
都有文件,但它们的内容不同,我们都会发生合并冲突。
由于你使用了-X theirs
,Git通过采用“他们的”更改来解决每个冲突(“他们的”是你命名的提交,而不是你作为HEAD
的那个),因为空的merge-base提交。
如果你希望Git假装其他一些提交是合并库,你可以使用git replace --graft
插入一些假的父链接。例如,假设你想在任意选择的提交C中将两者假装在一起:
A--o--o--...--L <-- branch1
/
B--...--C--...--R <-- branch2
所以Git会将C
与L
和C
与R
进行比较。就git merge
本身而言,你在A--...--L
链中选择哪个提交并不重要;任何提交都会做(包括A
和L
本身),但请注意Git只会“看到”自你选择的提交后的变化(由于C
-vs-L
和C
-vs-R
的差异)。因此,在链中选择一些适当的提交并运行:
git replace --graft <hash-ID-of-chosen-commit> <hash-ID-of-C>
现在,Git将使用替换(移植)提交而不是选择的提交。 git merge
现在将使用C
的内容作为共同来源。 (你可以在git merge
退出时立即删除移植物,即使它与合并冲突一起退出。因此你可以编写一个插入移植物的小脚本,运行git merge
,删除移植物,与任意选择的祖先合并。插入它作为L
的替代品,只要它在B--...--R
线上,或插入它作为R
的替代品,只要它在A--...--L
线上。)