我有一个本地git
存储库,其中包含一些我想删除的提交。更准确地说,我想重写整个存储库历史记录,就好像从未发生过给定的提交一样。例如,here和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历史记录是(作者/日期已删除)
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”有关的行上,用“ drop”替换“ pick”。
令我惊讶的是,git
无法管理该操作并且抱怨有冲突
Auto-merging foo.txt
CONFLICT (content): Merge conflict in foo.txt
当然,在这个简单的示例中,我可以手动解决冲突,但这违背了自动删除提交的想法。甚至更糟的是,在具有“第三”之后的进一步提交的存储库中,解决冲突后git rebase
再次抱怨“第三”之后的提交发生冲突,依此类推。
为什么git rebase
无法自动解决冲突?
是否有一种自动方式来删除“ second_bis”提交?
或者,是否有可能对历史记录中的每个提交应用补丁“ second_bis-> second”,然后最终删除并非没有的提交?
答案 0 :(得分:1)
问题是,完成对文件添加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来避免这种情况。)
答案 1 :(得分:0)
似乎您的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