...我想...删除最后 2 个提交。这可行吗?
你不能完全删除提交,但你可以很容易地告诉 Git 忘记它们。
最后,它的工作方式非常简单。我们首先注意到每个提交都会保存一个快照,并且还存储其 父 提交的哈希 ID(以及您的提交日志消息和您作为作者的姓名等)。这形成了一个向后指向的提交链。
如果我们让单个大写字母代表提交哈希 ID,我们可以绘制这个链:
... <-F <-G <-H <--master
请注意,分支名称,在本例中为master,将last 提交的哈希ID 存储在链中。 (当某个东西存储了提交的哈希 ID 时,我们说这个东西 指向 提交,因此是箭头。名称 master 指向 H,H 指向 @987654326 @,等等。)
Git 找到这些提交的方法是从master 中读取H 的哈希ID,它定位到提交H,然后读取提交H 并显示它。然后,在读取H 后,Git 的哈希 ID 为提交 G,因此 Git 可以读取 G 并显示它,依此类推。
当我们进行新的提交时,Git 实际上会这样做:
- 写出快照;
- 写出作者和日志信息等;
- 让 new 指向 current 提交;
- 最后也是最重要的,将 new 提交的哈希 ID 写入分支名称。
如果我们有:
...--F--G--H
我们添加了--I:
...--F--G--H--I
然后 Git 更改了 name master 以存储提交 I 的哈希 ID。最终我们有:
...--F--G--H--I--J <-- master
如果我们做了几个不需要的提交,我们可以告诉 Git:重新设置名称 master 指向提交 H 而不是提交 J。 有几种方法可以做到那个,但在这种情况下,第一个要达到的是git reset --hard(虽然我们已经检查了master,并确保你没有任何担心丢失的东西,因为git reset --hard告诉Git扔掉所有东西):
git checkout master
git reset --hard HEAD~2
~2 后缀告诉 Git 倒数两步——从技术上讲,两个 第一父级 步,这在我们的链中有一些合并提交时很重要,但在这里,我们没有不要紧。如果 master 当前指向 J,那么 Git 会倒数两次:J 到 I,然后是 I 到 H。然后,Git 用来自提交 H 的内容替换我们的工作 并且 使名称 master 指向 H 而不是 J:
I--J
/
...--F--G--H <-- master
现在J 很难找到,它似乎被删除了。
这样做的缺点是,如果我们让我们的 Git 告诉其他 Git:在这里,复制提交 I 和 J, 其他 Git 有两个提交和即使在我们的 Git 忘记了它们之后,它们也会重新引入到我们自己的 Git 中。但是,如果我们从未在其他任何地方成功发送过这两个提交,那么我们是唯一拥有它们的人,所以如果 我们忘记它们,它们就如同消失了一样.
(如果我们推送了它们,我们可以拥有我们的 Git,他们的 Git,以及所有其他的 Git从那时起,all 忘记它们,然后然后它们就会消失。但显然这很快就会变得困难。)