使用 git rebase 删除提交时发生冲突

Conflict when removing a commit with git rebase

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

要有一个具体可行的示例,请考虑按如下方式构建的 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 历史记录(Authors/Date 已删除)

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

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

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

是否有自动方法删除"second_bis"提交?

或者,是否可以对历史记录中的每个提交应用补丁 "second_bis -> second",然后最终删除什么都不做的提交?

看来你的second_bis是最后一次提交,你可以按如下方式做,

修改上次提交信息

git commit --amend
#change second_bis into third

重置上次提交

git reset HEAD~
git add *
git commit -a -m "third"
#now 3rd commit shows third

还原上次提交

如果您已经将更改推送到服务器,您可以恢复

git revert HEAD
#revert done change for third commit
git add *
git commit -a -m "third"
#now 3rd commit shows third

问题是,当通过在文件上添加 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 来避免这种情况)。