Question summary
I have tried git reset --hard <old_commit>
but that doesn't help because I can still view commits made after <old_commit>, i.e. descendants of <old_commit> using the commands git show <newer_commit>
or git log <newer_commit>
.
I want to revert the state of the repo to an older commit such that there is absolutely no evidence or trace of any newer commits that are descendants of the commit I reverted to. Can this be done?
Detailed question
I will my explain my question after I explain how I have set up my repo to reproduce the situation.
First I create a new repo and make 4 commits.
Here are the steps to quickly create an example repo that demonstrates my question.
mkdir foo
cd foo
git init
echo a > a.txt; git add a.txt; git commit -m "Add a.txt"
echo b > b.txt; git add b.txt; git commit -m "Add b.txt"
echo c > c.txt; git add c.txt; git commit -m "Add c.txt"
echo d > d.txt; git add d.txt; git commit -m "Add d.txt"
git log
I can see all 4 commits in the log.
lone@debian:~/foo$ git log
commit ae39b5666628d87abda5b82dbf8ede093946ec6d
Author: Lone Learner <lone@example.com>
Date: Thu Dec 10 19:01:29 2015 +0530
Add d.txt
commit cc1843682a5f73c382e902d3db50c06d7d738fb0
Author: Lone Learner <lone@example.com>
Date: Thu Dec 10 19:01:20 2015 +0530
Add c.txt
commit 95ed593fc7ab8f23b0584d0f34a47aca28190f11
Author: Lone Learner <lone@example.com>
Date: Thu Dec 10 19:01:08 2015 +0530
Add b.txt
commit 14bdb2d20c730a77fd413f6b577c1afa93c8d32d
Author: Lone Learner <lone@example.com>
Date: Thu Dec 10 19:00:58 2015 +0530
Add a.txt
Now I realize that the 3rd and 4th commits were mistakes. They should never have been done. I don't want to share those commits with anyone. I haven't pushed these commits anywhere or not shared these commits with anyone by any means yet. I want to revert the state of the repo to what it used to be before c.txt was added. In other words, it should look like that the 3rd and 4th commit never happened at all.
This would have been easy if I had cloned the repo just after adding b.txt and kept that clone as a backup. The backup clone would be in the state that I desire now. But in reality, I haven't made a clone at that point and now I want to change the repo as if nothing ever happened after adding b.txt.
I tried hard reset to the 2nd commit, i.e. the commit where I added b.txt.
lone@debian:~/foo$ git reset --hard 95ed593fc7ab8f23b0584d0f34a47aca28190f11
HEAD is now at 95ed593 Add b.txt
lone@debian:~/foo$ git log
commit 95ed593fc7ab8f23b0584d0f34a47aca28190f11
Author: Lone Learner <lone@example.com>
Date: Thu Dec 10 19:01:08 2015 +0530
Add b.txt
commit 14bdb2d20c730a77fd413f6b577c1afa93c8d32d
Author: Lone Learner <lone@example.com>
Date: Thu Dec 10 19:00:58 2015 +0530
Add a.txt
But the 3rd and 4th commit are still accessible via their commit IDs. For example, here is how I can still see the 3rd commit where I added c.txt.
lone@debian:~/foo$ git show cc1843682a5f73c382e902d3db50c06d7d738fb0
commit cc1843682a5f73c382e902d3db50c06d7d738fb0
Author: Lone Learner <lone@example.com>
Date: Thu Dec 10 19:01:20 2015 +0530
Add c.txt
diff --git a/c.txt b/c.txt
new file mode 100644
index 0000000..f2ad6c7
--- /dev/null
+++ b/c.txt
@@ -0,0 +1 @@
+c
How can I change the repo to a state where it would look like the 3rd and 4th commit never happened? There should be absolutely no evidence of the commits I want to lose.