Git merge不会删除其他存储库中的文件

时间:2018-03-05 22:35:33

标签: git git-merge git-remote svnsync

存在两个存储库: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

a"合并" branch是从rep1 / master

的尖端创建的
git checkout -b merge-master-branches master 

使用选项"他们的"执行合并和南瓜。 由于合并来自另一台服务器,因此需要不相关的历史记录。

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

观察到的是不删除rep1 / file1.txt。

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

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

1 个答案:

答案 0 :(得分:0)

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

Git的git merge通过将两个分支提示与一个公共合并库进行比较来实现。也就是说,如果你绘制提交图,它看起来像这样:

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

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

左侧发生了从​​*L的变化。从*R的任何变化都发生在右侧。 Git结合了这两个“发生的事情”,将这些组合的更改应用于*的内容,如果一切顺利,则从结果中进行新的提交。

但您正在使用--allow-unrelated-histories。当没有共同提交时,这是 :我们绘制LR的历史记录,并发现它们从不偏离共同点。例如,我们可能会得到:

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

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

其中AB 都是 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中的形式新创建的。无论这些文件匹配在哪里,一切都很好:我们只需要获取该文件。只要LR没有的文件,反之亦然,一切都很好:我们只拿这个文件。只要LR都有文件,但其内容不同,我们就会发生合并冲突。

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

如果您希望Git假装某些其他提交是合并库,您可以使用git replace --graft插入一些假的父链接。例如,假设你想在任意选择的提交C:

中伪造两者
A--o--o--...--L   <-- branch1
         /
B--...--C--...--R   <-- branch2

以便Git将CLCR进行比较。就git merge本身而言,在A--...--L链中选择哪个提交无关紧要; 任何提交都会(包括AL),但请注意,Git只会“看到”自您选择的提交后的更改(由于差异{{1} } -vs - CL - vs - C)。因此,在链中选择一些适当的提交并运行:

R

并且Git现在将使用替换(移植)提交而不是所选的提交。 git replace --graft <hash-ID-of-chosen-commit> <hash-ID-of-C> 现在将使用git merge的内容作为公共来源。 (您可以在C退出后立即删除移植,即使它以合并冲突退出。因此,您可以编写一个插入移植物的小脚本,运行git merge并删除移植物,与任意选择的祖先合并。只要将其插入git merge,只需将其插入L行,或将其作为B--...--R的替换插入,只要它位于R上即可。 A--...--L行。)