[英]Git merge does not deleting files from another repository
存在两个存储库:rep1、rep2。 两者都是来自同一个 SVN 实例的单向同步的结果。 (SVN 中的变化同步到 git,但 git 中的变化没有同步回 SVN)这两个存储库不是彼此的 fork。
rep1/master 分支包含一个文件 file1.txt
rep2/master 分支包含文件 file1.txt,但该文件在 rep2/ 中被删除
rep2 作为远程添加到 rep1 中以便合并。 (远程2)
创建分支 rep2/master
git checkout -b rep2_master_branch --track rep2/master
从 rep1/master 的尖端创建一个“合并”分支
git checkout -b merge-master-branches master
使用选项“他们的”执行合并并压缩。 由于合并来自另一台服务器,因此需要 allow-unrelated-history。
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
的历史L
,发现它们从未偏离共同点。 例如,我们可能会得到:
A--o--o--...--L <-- branch1
B--o--...--o--R <-- branch2
其中A
和B
都是根的提交。 那么 Git应该使用什么作为共同的起点,以找出自那时以来发生了什么变化?
人们可以为自己选择的各种起点争论不休,但 Git 的答案是:使用空提交。 也就是说,使用--allow-unrelated-histories
,Git 假装有一个根本没有文件的常见提交:
A--o--o--...--L <-- branch1
/
*
\
B--o--...--o--R <-- branch2
将空的 commit *
与提交L
,Git 发现branch1
上的每个文件都是以其在L
中的形式新创建的。 将*
与R
进行比较,Git 发现branch2
上的每个文件都是以其在R
中的形式新创建的。 无论这些文件在哪里匹配,一切都很好:我们只需要那个文件。 只要L
有一个R
没有的文件,反之亦然,一切都很好:我们只需要那个文件。 只要L
和R
都有文件,但它们的内容不同,就会发生合并冲突。
由于您使用了-X theirs
,Git 通过采取“他们的”更改(“他们的”是您命名的提交,而不是您作为HEAD
提交的提交)来解决每个冲突,因为空合并基础提交。
如果你想让 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
并删除嫁接的小脚本,以与任意选择的祖先合并. 只要它在B--...--R
行上,只需将其插入为L
的替换,或者只要它在A--...--L
行上, A--...--L
其插入为R
的替换.)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.