2

存在两个存储库:rep1、rep2。两者都是来自同一个 SVN 实例的单向同步的结果。(SVN 中的更改会同步到 git,但 git 中的更改不会同步回 SVN)这两个存储库不是彼此的分支。

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 

使用选项“他们的”和壁球执行合并。由于合并来自另一台服务器,因此需要允许不相关的历史记录。

git merge -Xtheirs --squash rep2_master_branch  --allow-unrelated-histories

观察到的是 rep1/file1.txt 没有被删除。

进一步观察,合并期间的冲突已正确解决,修改和添加的文件也是如此。似乎唯一遗漏的是在 rep2 中已删除的文件。

我该如何解决这个问题?或者更好的是,如何解决这个问题?

4

1 回答 1

2

就 Git 而言,这正确的合并结果。

Gitgit merge通过将两个分支提示与一个通用合并基础进行比较来工作。也就是说,如果你绘制提交图,它看起来像这样:

             o--o--L   <-- branch1
            /
...--o--o--*
            \
             o--o--R   <-- branch2

branch1然后将(commit L) 与branch2(commit )合并的结果R将通过比较 commit 的内容(*两个分支派生的公共点)与 commit 的内容和 commitL的内容来计算R

无论从*L发生在左侧。无论从*R发生在右侧。Git 将这两个“发生的事情”结合起来,将这些结合后的更改应用于 的内容*,如果一切顺利,则从结果中进行新的提交。

但是您正在使用--allow-unrelated-histories. 没有共同提交时才需要这样做:我们绘制 和 的历史LR发现它们从未偏离共同点。例如,我们可能会得到:

A--o--o--...--L   <-- branch1

B--o--...--o--R   <-- branch2

whereABare都是根提交。那么Git应该使用什么作为共同的起点,以找出从那时起发生了什么变化?

人们可以为自己选择的各种起点争论不休,但 Git 的答案是:使用空提交。 也就是说,使用--allow-unrelated-histories,Git 假装有一个根本没有文件的共同提交:

  A--o--o--...--L   <-- branch1
 /
*
 \
  B--o--...--o--R   <-- branch2

比较*空的 commit 和 commit L,Git 发现上面的每个文件branch1都是以它在L. 与 相比*RGit 发现上面的每个文件branch2都是以它在R. 无论这些文件在哪里匹配,一切都很好:我们只需要那个文件。无论哪里L有一个文件R没有,反之亦然,一切都很好:我们只是拿那个文件。无论在哪里都有一个文件LR但它们的内容不同,我们就会有合并冲突。

由于您使用-X theirs了 ,Git 通过采取“他们的”更改来解决每个冲突(“他们的”是您命名的提交,而不是您作为 的提交HEAD),因为是空的合并基础提交。

如果你想让 Git 假装其他提交是合并基础,你可以使用git replace --graft插入一些假的父链接。例如,假设您想在任意选择的提交 C 处将两者假绑定在一起:

A--o--o--...--L   <-- branch1
         /
B--...--C--...--R   <-- branch2

以便 Git 将与CL进行C比较R。就其本身而言,您在链git merge中选择哪个提交并不重要。任何提交都可以(包括它们自己) ,但请注意 Git 只会“看到”自您选择的提交以来的更改(由于-vs-和-vs-的差异)。因此,在链中选择一些适当的提交并运行:A--...--LALCLCR

git replace --graft <hash-ID-of-chosen-commit> <hash-ID-of-C>

并且 Git 现在将使用替换(移植)提交而不是选择的提交。Agit merge现在将使用 的内容C作为公共源。(您可以在git merge退出后立即删除嫁接,即使它以合并冲突退出。因此,您可以编写一个插入嫁接、运行git merge和删除嫁接的小脚本,以与任意选择的祖先合并。只需插入它L只要在线就作为替换,或者只要B--...--R在线就插入作为替换。)RA--...--L

于 2018-03-05T23:06:43.520 回答