I have a local git
repository containing some commits I would like to remove. More precisely, I would like to rewrite the entire repository history as if the given commits never took place. Removing old commits have been discussed here and here for example, but for some reasons it is not working for me.
To have a concrete workable example, consider a git repository constructed as follows
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
The git repository now contains a single file foo.txt
, which contains
hello
hello2 bis
hello3
The full git history obtained by ```git log -p --all`` is (Authors/Date removed)
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
At this point, suppose I would like to eliminate the commit with comment "second_bis", so to have a history like the following
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
The approach I tried is to use git rebase
as to simply eliminate the commit "second_bis"
git rebase -i 853dca5b
This opens my editor with a file containing
pick c2c7f8c second_bis
pick 7bd2f44 third
# Rebase 853dca5..7bd2f44 onto 853dca5 (2 commands)
#
#...
At this point, I substitute "pick" with "drop" on the line pertaining to "second_bis".
To my surprise, git
is not able to manage the operation and complains with a conflict
Auto-merging foo.txt
CONFLICT (content): Merge conflict in foo.txt
Of course I can manually resolve the conflict in this simple example, but this defies the idea of automatically remove a commit. Even worse, on a repository with further commits after "third", after resolving the conflict git rebase
complains again with a conflict on commits after the "third" one, and so on.
Why is git rebase
unable to solve the conflict automatically?
Is there an automated way to remove the "second_bis" commit?
Alternatively, would it be possible to, say, apply a patch "second_bis -> second" to every commits in the history, and then eventually remove commits which do not nothing?
the problem is that when the change by the revision that adds hello3 on the file is done, the previous line is "hello2 bis" not just "hello 2" and there's nothing after the affected line on the original revision so git can't really tell what's going on. give git a little more context by adding hello3 before the sed and it works like a charm:
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
as a side note, your instructions will also work if instead of having a file with 1, 2, 3 lines, you try in the middle of a file that has at least a cumple of lines before and another couple of lines after. the abrupt EOF is what is reaaly confusing git to do its job (which I avoided by adding hello3 before the sed, obviously).