如何将私有git repo恢复到较早的点,以便在该点之后没有任何提交的痕迹? 问题摘要

如何将私有git repo恢复到较早的点,以便在该点之后没有任何提交的痕迹? 问题摘要,git,version-control,Git,Version Control,我尝试过git reset--hard,但这没有帮助,因为我仍然可以查看在之后进行的提交,即使用命令git show或git log的后代 我想将repo的状态还原为一个旧的提交,这样就绝对没有证据或跟踪任何新的提交是我还原到的提交的后代。这能做到吗 详细问题 在我解释如何建立回购协议以再现这种情况后,我将解释我的问题 首先,我创建一个新的回购协议并提交4次 下面是快速创建示例回购协议的步骤,该示例演示了我的问题 mkdir foo cd foo git init echo a > a.t

我尝试过
git reset--hard
,但这没有帮助,因为我仍然可以查看在之后进行的提交,即使用命令
git show
git log
的后代

我想将repo的状态还原为一个旧的提交,这样就绝对没有证据或跟踪任何新的提交是我还原到的提交的后代。这能做到吗

详细问题 在我解释如何建立回购协议以再现这种情况后,我将解释我的问题

首先,我创建一个新的回购协议并提交4次

下面是快速创建示例回购协议的步骤,该示例演示了我的问题

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
我可以在日志中看到所有4次提交

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
lone@debian:~/foo$git日志
提交AE39B566628D87ABDA5B82DBF8EDE093946EC6D
作者:孤独的学习者
日期:2015年12月10日星期四19:01:29+0530
添加d.txt
提交cc1843682a5f73c382e902d3db50c06d7d738fb0
作者:孤独的学习者
日期:2015年12月10日星期四19:01:20+0530
添加c.txt
提交95ed593fc7ab8f23b0584d0f34a47aca28190f11
作者:孤独的学习者
日期:2015年12月10日星期四19:01:08+0530
添加b.txt
提交14bdb2d20c730a77fd413f6b577c1afa93c8d32d
作者:孤独的学习者
日期:2015年12月10日星期四19:00:58+0530
添加一个.txt文件
现在我意识到第三次和第四次犯了错误。他们不应该这样做。我不想和任何人分享这些承诺。我还没有将这些提交推到任何地方,也没有以任何方式与任何人共享这些提交。我想将回购的状态恢复到添加c.txt之前的状态。换句话说,看起来第三次和第四次犯罪根本就没有发生过

如果我在添加b.txt之后克隆了repo,并将该克隆作为备份,那么这将很容易。备份克隆将处于我现在想要的状态。但事实上,我当时还没有做过克隆,现在我想改变回购协议,就好像添加了b.txt之后什么都没发生一样

我尝试了硬复位到第二次提交,即我添加了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
lone@debian:~/foo$git重置—硬95ed593fc7ab8f23b0584d0f34a47aca28190f11
HEAD现在位于95ed593 Add b.txt
lone@debian:~/foo$git日志
提交95ed593fc7ab8f23b0584d0f34a47aca28190f11
作者:孤独的学习者
日期:2015年12月10日星期四19:01:08+0530
添加b.txt
提交14bdb2d20c730a77fd413f6b577c1afa93c8d32d
作者:孤独的学习者
日期:2015年12月10日星期四19:00:58+0530
添加一个.txt文件
但是第三次和第四次提交仍然可以通过其提交ID访问。例如,我仍然可以看到我添加了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
lone@debian:~/foo$git show cc1843682a5f73c382e902d3db50c06d7d738fb0
提交cc1843682a5f73c382e902d3db50c06d7d738fb0
作者:孤独的学习者
日期:2015年12月10日星期四19:01:20+0530
添加c.txt
diff——git a/c.txt b/c.txt
新文件模式100644
索引0000000..f2ad6c7
---/dev/null
+++b/c.txt
@@ -0,0 +1 @@
+c
我如何才能将回购协议更改为第三次和第四次提交似乎从未发生过的状态?应该绝对没有我想要丢失的提交的证据。

您应该执行Joseph Silber前面提到的“git reset--hard”。 当垃圾收集器运行时,如果您不希望看到的提交挂起提交,那么它最终将消失。 如果要强制清理,请使用命令“git-gc”(请参阅和)

对我有效。我已把它标为正确答案。为了将来的参考,我记下了在遵循他的步骤后对我有用的步骤

git reset --hard 95ed593fc7ab8f23b0584d0f34a47aca28190f11
git reflog expire --expire-unreachable=now --all
git gc --prune=now
一旦完成此操作,尝试访问任何删减的提交将导致
坏对象
错误。例如:

lone@debian:~/foo$ git show cc1843682a5f73c382e902d3db50c06d7d738fb0
fatal: bad object cc1843682a5f73c382e902d3db50c06d7d738fb0

这应该可以回答你的问题:@TheEye链接问题的哪一个答案回答了我的问题?我发现只有这里提到的
git reset
方法是相关的,但正如我在这个问题中解释的那样,
git reset--hard
方法对我不起作用,因为我仍然可以使用
git show
git log
访问旧提交(我想丢失的提交)。git reset只会丢弃本地更改,你需要像git这样的东西。你读过提议的解决方案了吗?它们非常详尽。@ye我阅读了所有这些解决方案,我知道所有这些解决方案
git revert
肯定不能解决这个问题,因为它不会重写历史。我的问题的解决方案肯定需要重写历史,并以一种不会留下任何新的犯罪痕迹的方式重写。当然,危险的作品,也许这会有帮助:我确实做了
git重置--hard 95ed593fc7ab8f23b05840f34a47aca28190f11
然后是
git gc--prune=all
但是我仍然可以看到
git show cc1843682a5f73c382d3db50c6d7d738fb0
。试试“git reflog expire--expire unreable=now--all”然后是“git gc--prune=now”谢谢!这起作用了。你知道为什么我尝试执行git-gc--prune=all失败了吗?那是因为这些对象仍然在reflog中被引用。这是Git中的一个安全网,因此自动修剪不会太快地破坏对象。通常,即使在执行纯“git reset--hard”命令后仍然引用对象,提交也不会再出现。这种行为适合大多数人,而且更安全。