繁体   English   中英

Git 合并不会从另一个存储库中删除文件

[英]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 没有共同提交时才要这样做:我们绘制LR的历史L ,发现它们从未偏离共同点。 例如,我们可能会得到:

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

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

其中AB都是根的提交。 那么 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没有的文件,反之亦然,一切都很好:我们只需要那个文件。 只要LR都有文件,但它们的内容不同,就会发生合并冲突。

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

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

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

以便 Git 将CL以及CR 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并删除嫁接的小脚本,以与任意选择的祖先合并. 只要它在B--...--R行上,只需将其插入为L的替换,或者只要它在A--...--L行上, A--...--L其插入为R的替换.)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM