...我想...删除最后 2 个提交。这可行吗?
你不能完全删除提交,但你可以很容易地告诉 Git忘记它们。
最后,它的工作方式非常简单。我们首先注意到每个提交都会保存一个快照,并且还存储其父提交的哈希 ID(以及您的提交日志消息和您作为作者的姓名等)。这形成了一个向后指向的提交链。
如果我们让单个大写字母代表提交哈希 ID,我们可以绘制这个链:
... <-F <-G <-H <--master
请注意,在这种情况下,分支名称存储链中最后一次提交master
的哈希 ID 。(当某物存储提交的哈希 ID 时,我们说该物指向该提交,因此是箭头。名称指向,指向,依此类推。)master
H
H
G
Git 找到这些提交的方式是读取H
out of的哈希 ID master
,它定位 commit H
,然后读取 commitH
并显示它。然后,在 readH
之后,Git 的哈希 ID 为 commit G
,因此 Git 可以读取G
并显示它,依此类推。
当我们进行新的提交时,Git 实际上是通过以下方式完成的:
- 写出快照;
- 写出作者和日志信息等;
- 将新点返回到当前提交;
- 最后也是最重要的,将新提交的哈希 ID 写入分支名称。
所以如果我们有:
...--F--G--H
我们补充说--I
:
...--F--G--H--I
然后 Git 更改了名称 master
以存储 commit 的哈希 ID I
。最终我们有:
...--F--G--H--I--J <-- master
如果我们做了几个不需要的提交,我们可以告诉 Git:重新设置名称master
以指向 commitH
而不是 commit 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 将我们的工作替换为来自 commit 的内容H
,并使名称master
, 指向H
而不是J
:
I--J
/
...--F--G--H <-- master
现在J
很难找到,它似乎已被删除。
这样做的缺点是,如果我们让我们的 Git 告诉其他 Git:在这里,复制提交I
和J
,其他 Git 有这两个提交,并且即使在我们的 Git 忘记它们之后,也会将它们重新引入我们自己的 Git . 但是,如果我们从未在其他任何地方成功发送过这两个提交,那么我们就是唯一拥有它们的人,所以如果我们忘记它们,它们就如同消失了一样好。
(如果我们推送了它们,我们可以拥有我们的 Git,以及他们的Git,以及从那时起拾取它们的所有其他 Git ,都忘记它们,然后它们就会消失。但显然这很快就会变得困难。)