避免在包含合并提交的Git变基中重新解决冲突

6

尝试将一个仓库的历史记录转移到另一个没有共同祖先的仓库,方法是添加源远程并在本地目标仓库上的一个分支上进行变基。

源代码:

A-B-C
 \ /
  E

需要的目标:

F-A'-B'-C'
   \   /
     E'

git rebase --rebase-merges的文档称它会保留拓扑结构并重新创建合并提交,但是:

这些合并提交中解决的任何冲突或手动修改都必须手动解决/重新应用。

现在,我想避免重新解决冲突,我对为什么需要这样做感到困惑。合并提交的内容已经在那里了,我可以将HEAD分离。

所以,我尝试了:

$ git rebase -i --onto destnewbranch --root --rebase-merges srcbranch
Could not apply C... master # Merge branch 'master'

(detached HEAD|REBASE x/y)
$ git status
interactive rebase in progress; onto F
Last commands done (n commands done):
   pick B
   merge -C C master # Merge branch 'master' 

You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

为了解决冲突问题,我正在采用C盘的内容。
$ git reset --hard C

现在的内容不错,但历史记录不行,所以:

$ git reset --soft HEAD@{1}

现在只需要继续进行变基操作:

$ git commit
$ git rebase --continue

然而,历史是错误的,因为我现在只剩下:

F-A'-B'-C'

C'并不是一个合并提交,尽管它包含了B和E的修改结果。

那些没有引起冲突的合并提交,在重新设置时可以成功地保留拓扑结构。

我认为是我在重置时搞糊涂了REBASE的MERGING状态,并且最终的git提交将不会创建一个合并提交,而是一个普通的提交。如果我不进行重置并手动解决冲突,git commit 将会创建一个合并提交。

git版本号为2.26.0.windows.1


通常情况下,当两个分支的历史记录分叉(通常是由于变基)并在不同的差异中产生相同的更改时,就会出现这种情况。几天前,我自己做了这件事,推送了它,然后才意识到问题,接着又不得不重新变基并在每个后续提交中解决冲突。我不知道是否有更好的解决方案,但期待看到团队提出的想法。 - erik258
1个回答

3

使用 git restore 命令可以使用已有提交的内容解决冲突,不要使用会修改 HEADgit reset --hard 命令。

然而,在大多数情况下,即使使用这种方式也无法解决冲突。您可能需要找的是叫做 rerere("重用记录的解决方案")的功能。在 Git 配置中启用它:

git config rerere.enabled true

启用此功能后,将记录所有已解决的冲突,并允许稍后重现它们。为了自动暂存这些记录的冲突,您还可以设置rerere.autoupdate

git config rerere.autoupdate true

此外,你可以使用 Git(在 Ubuntu 上通常在 /usr/share/doc/git/contrib/rerere-train.sh 可用)分发的 rerere-train.sh 脚本来教导 rerere 处理过去的合并和已解决的冲突。在变基之前调用它,以避免重新执行任何以前解决过的冲突:

rerere-train.sh destnewbranch..srcbranch
git rebase destnewbranch srcbranch --onto destnewbranch --rebase-merges

尝试使用git restore而不是git reset。不幸的是,它会在每次冲突合并时清除F中的更改。由于我只添加了一个文件到F中,我从F中恢复了该文件,以便我可以继续... - Mart
然而,我在子模块方面遇到了障碍。无论使用--recurse-submodules选项,命令git restore --source C -- .都不会将更改带到子模块HEAD。我注意到它选择了C之后的下一个提交(这里有更多比简化示例更复杂的情况),并且在重新设置基础时与子模块发生了冲突。尝试使用git checkout --theirs submodule,结果出现了$ git submodule status U0000000000000000000000000000000000000000。失败。 - Mart
尝试了 rerere,但在 rerere-train.sh 过程中遇到了二进制文件的问题:警告:无法合并二进制文件:system.hdf(我们的 vs. 他们的) 错误:无法解析 'system.hdf' 中的冲突块。毫不奇怪,在 rebase 合并期间这些二进制文件无法自动解决。总的来说,这是一个巨大的失败。 - Mart
1
rerere,像其他大多数Git功能一样,不支持二进制文件。我认为在二进制文件中自动重新解决冲突没有简单的方法。也许你可以避免变基,改用 git merge --allow-unrelated-histories - Etienne Laurin
试图避免使用git merge --allow-unrelated-histories,但似乎这是最可行的解决方案。 - Mart

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接