如何在使用rebase -ir处理之前的无关提交后重做合并冲突解决方案?

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

举一个简单的例子,假设我们有一个repo,其中一个不正确的行被添加到文件a

$ git init 
Initialized empty Git repository in /someplace/.git/
$ echo "a1\nb2" > a
$ echo b1 > b    
$ git add .
$ git commit -m init  
[master (root-commit) 917f3b9] init
 2 files changed, 3 insertions(+)
 create mode 100644 a
 create mode 100644 b

分支master然后分叉新的分支f

$ git branch f

master中,我们然后在不正确的文件中添加另一行。

$ echo b3 >> a
$ git commit -am 'added b3 to a' 
[master e44bc9f] added b3 to a
 1 file changed, 1 insertion(+)

在分支f,我们做一些无关的事情,提交它,

$ git checkout f
$ echo c1 > c 
$ git add .
$ git commit -m "added c"
  1 label onto
[f 7cb63b2] added c
 1 file changed, 1 insertion(+)
 create mode 100644 c

然后我们将错误放置在文件a中的行移动到文件b。

$ echo b2 >> b
$ sed -i '/b2/d' a
$ git commit -am "moved b2 to where it really belongs"
[f 32cee76] moved b2 to where it really belongs
 2 files changed, 1 insertion(+), 1 deletion(-)

然后我们尝试将master合并到f,但遇到了master添加了另一条不正确的线而f删除了第一条线的冲突。

$ git merge master 
Auto-merging a
CONFLICT (content): Merge conflict in a
Automatic merge failed; fix conflicts and then commit the result.
$ cat a
a1
<<<<<<< HEAD
=======
b2
b3
>>>>>>> master

要解决冲突,我们将第二行不正确的行移动到正确的文件,然后提交合并。

$ echo b3 >> b
$ sed -i '/HEAD/,$d' a
$ git commit -a --no-edit 
[f 28d8543] Merge branch 'master' into f

然后,我们意识到关于c的提交不应该在这个分支中,所以我们用rebase -ir“删除”它并遇到与之前相同的冲突。

$ git rebase -ir $(git merge-base master @) # remove the commit about c
Auto-merging a
CONFLICT (content): Merge conflict in a
Could not apply 28d8543... onto # Merge branch 'master' into f
$ cat a
a1
<<<<<<< HEAD
=======
b2
b3
>>>>>>> refs/rewritten/onto

那么,考虑到在冲突中没有出现的b添加的内容,这里最简单,最有效和最通用的解决方案是重做以前的解决方案吗?

git git-rebase git-merge-conflict
2个回答
1
投票

有一个git实用程序用于记录冲突的解决方式,以便您以后可以重放。它被称为git rerere

它真的意味着特定的用例 - 并且由于该用例是基于我不同意的假设,我几乎从不使用git rerere

我还要说,如果没有一个良好的工作流程,你所描述的场景应该是不常见的,所以我个人不会开始使用rerere记录每一个冲突解决方案,只是因为我以后再次需要它。

但是......因为那是你提出的问题,git rerere可能是“答案”。


0
投票

到目前为止想到的最佳解决方案(实际上并不是那么好)是放弃git并制作合并冲突解决方案的补丁:

$ cp -a . ../$(basename $PWD)~
$ echo b3 >> b
$ sed -i '/HEAD/,$d' a
$ diff -ru ../$(basename $PWD)~ .
diff -ru ../t~/a ./a
--- ../t~/a 2019-03-08 12:54:34.701197573 -0800
+++ ./a 2019-03-08 12:54:56.761197321 -0800
@@ -1,6 +1 @@
 a1
-<<<<<<< HEAD
-=======
-b2
-b3
->>>>>>> refs/rewritten/onto
diff -ru ../t~/b ./b
--- ../t~/b 2019-03-08 12:54:34.701197573 -0800
+++ ./b 2019-03-08 12:54:54.044530686 -0800
@@ -1,2 +1,3 @@
 b1
 b2
+b3

我可以在某处保存该补丁,并在需要再次解决此问题时应用它。这样做的问题是管理这些补丁,并且当我需要重做冲突解决方案或者总是对每个冲突解决方案进行修补时,要么预测这个补丁。

不过,我更喜欢使用git来管理它的解决方案。


0
投票

git rerere或制作refs/rewritten/onto补丁是必要的,因为,在Git 2.23中,refs/rewritten/onto将在git rebase -ir中止的特定情况下被移除。 “git rebase --abort”在结束“refs/rewritten/”时曾经离开过git rebase -r,这已被纠正。

参见commit d559f50commit 37e9ee5commit d3fce47commit 7372eaePhillip Wood (phillipwood)(2019年5月14日)。 (Junio C Hamano -- gitster --commit 88f95e4合并,2019年7月9日)

rebase --abort/--quit:清理refs/rewritten

rebase -r完成时,它会移除它创建的refs/rewritten下的任何引用。 但是,如果用户中止或退出,则不删除rebase引用。这可能会导致未来的退货问题。

例如,我最近想将主题分支的更新版本合并到集成分支中,因此运行rebase -ir并从todo列表中删除主题分支的选择和标签,以便

merge -C <old-merge> topic

会拿起新版主题。 不幸的是,refs/rewritten/topic已经存在于先前已被中止的rebase中,因此rebase只使用了旧主题,而不是新主题。

非交互式退出案例的逻辑已更改,以确保始终释放buf

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