首页 > 解决方案 > 使用 git rebase 删除提交时发生冲突

问题描述

我有一个本地git存储库,其中包含一些我想删除的提交。更准确地说,我想重写整个存储库历史,就好像给定的提交从未发生过一样。例如,已在此处此处讨论了删除旧提交,但由于某些原因,它对我不起作用。

为了有一个具体可行的例子,考虑一个如下构造的 git 存储库

git init .
echo hello >foo.txt
git add foo.txt
git commit -a -m first
echo hello2 >>foo.txt
git commit -a -m second
sed -i 's/hello2/hello2 bis/' foo.txt
git commit -a -m second_bis
echo hello3 >>foo.txt
git commit -a -m third

git 存储库现在包含一个文件foo.txt,其中包含

hello
hello2 bis
hello3

```git log -p --all`` 获得的完整 git 历史是(作者/删除日期)

commit 7bd2f440ef5a0cbfd0fd252671d1651a6c282db5
Author: ---
Date: ---

    third

diff --git a/foo.txt b/foo.txt
index 83d1cb0..ce5a249 100644
--- a/foo.txt
+++ b/foo.txt
@@ -1,2 +1,3 @@
 hello
 hello2 bis
+hello3

commit c2c7f8c66ddb40fc6196350ea5e4f4c54293cf54
Author: ---
Date: ---

    second_bis

diff --git a/foo.txt b/foo.txt
index 97531f3..83d1cb0 100644
--- a/foo.txt
+++ b/foo.txt
@@ -1,2 +1,2 @@
 hello
-hello2
+hello2 bis

commit 853dca5b3c9152ab50cdf9de260f1a3b4bba4100
Author: ---
Date: ---

    second

diff --git a/foo.txt b/foo.txt
index ce01362..97531f3 100644
--- a/foo.txt
+++ b/foo.txt
@@ -1 +1,2 @@
 hello
+hello2

commit 921efb9472e14333804dff575a71050213a770be
Author: ---
Date: ---

    first

diff --git a/foo.txt b/foo.txt
new file mode 100644
index 0000000..ce01362
--- /dev/null
+++ b/foo.txt
@@ -0,0 +1 @@
+hello

此时,假设我想消除带有注释“second_bis”的提交,所以有如下的历史记录

commit 7bd2f440ef5a0cbfd0fd252671d1651a6c282db5
Author: ---
Date: ---

    third

diff --git a/foo.txt b/foo.txt
index 83d1cb0..ce5a249 100644
--- a/foo.txt
+++ b/foo.txt
@@ -1,2 +1,3 @@
 hello
 hello2
+hello3

commit 853dca5b3c9152ab50cdf9de260f1a3b4bba4100
Author: ---
Date: ---

    second

diff --git a/foo.txt b/foo.txt
index ce01362..97531f3 100644
--- a/foo.txt
+++ b/foo.txt
@@ -1 +1,2 @@
 hello
+hello2

commit 921efb9472e14333804dff575a71050213a770be
Author: ---
Date: ---

    first

diff --git a/foo.txt b/foo.txt
new file mode 100644
index 0000000..ce01362
--- /dev/null
+++ b/foo.txt
@@ -0,0 +1 @@
+hello

我尝试使用的方法是git rebase简单地消除提交“second_bis”

git rebase -i 853dca5b

这将打开我的编辑器,其中包含一个文件

pick c2c7f8c second_bis
pick 7bd2f44 third
# Rebase 853dca5..7bd2f44 onto 853dca5 (2 commands)
#
#...

在这一点上,我在与“second_bis”有关的行中将“pick”替换为“drop”。令我惊讶的git是,无法管理操作并抱怨冲突

Auto-merging foo.txt
CONFLICT (content): Merge conflict in foo.txt

当然,我可以在这个简单的示例中手动解决冲突,但这违背了自动删除提交的想法。更糟糕的是,在“第三次”之后有进一步提交的存储库上,在解决冲突后git rebase再次抱怨“第三次”之后的提交冲突,依此类推。

为什么git rebase无法自动解决冲突?

是否有自动删除“second_bis”提交的方法?

或者,是否有可能对历史中的每个提交应用补丁“second_bis -> second”,然后最终删除不执行任何操作的提交?

标签: gitgit-rebase

解决方案


问题是,当在文件上添加 hello3 的修订完成更改时,前一行是“hello2 bis”而不仅仅是“hello 2”,并且在原始修订的受影响行之后没有任何内容,所以 git 不能真的告诉你发生了什么事。通过在 sed 之前添加 hello3 为 git 提供更多上下文,它就像一个魅力:

git init .
echo hello >foo.txt
git add foo.txt
git commit -m first foo.txt
echo hello2 >>foo.txt
git commit -m second foo.txt
echo hello3 >>foo.txt
git commit -m third foo.txt
sed -i 's/hello2/hello2 bis/' foo.txt
git commit -m second_bis foo.txt
echo hello4 >> foo.txt
git commit -m hello4 foo.txt

附带说明一下,如果您尝试在文件中间尝试之前至少有几行,之后再有几行的文件,而不是拥有 1、2、3 行的文件,那么您的说明也将起作用。突然的 EOF 是真正让 git 无法完成其工作的原因(显然,我通过在 sed 之前添加 hello3 来避免这种情况)。


推荐阅读