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

问题描述 投票:0回答:1

存在两个存储库: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-merge git-remote svnsync
1个回答
0
投票

就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。只有在没有共同提交时才需要这样做:我们绘制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的那个),因为空的merge-base提交。

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

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

所以Git会将CLCR进行比较。就git merge本身而言,你在A--...--L链中选择哪个提交并不重要;任何提交都会做(包括AL本身),但请注意Git只会“看到”自你选择的提交后的变化(由于C-vs-LC-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线上。)

© www.soinside.com 2019 - 2024. All rights reserved.