我不小心输入了 git commit --amend 命令,这是一个错误,因为我意识到提交实际上是全新的,应该使用新消息进行提交。 我想创建一个新的提交。我该如何撤销之前的命令?
我不小心输入了 git commit --amend 命令,这是一个错误,因为我意识到提交实际上是全新的,应该使用新消息进行提交。 我想创建一个新的提交。我该如何撤销之前的命令?
PetSerAl的评论是关键。以下是两个命令序列,可以实现您想要的操作:
git reset --soft @{1}
git commit -C @{1}
当您进行新提交时,Git通常会使用以下事件序列:
a123456...
)(通过HEAD
,它给出了当前分支)。 让我们称此ID为C(用于当前)。 请注意,此当前提交具有父提交; 让我们称其ID为P(用于父级)。使用--amend
时,Git会稍微更改该过程。 它仍然像以前一样编写新提交,但在步骤3中,它不是使用parent = C编写新提交,而是使用parent = P来编写它。
从图示上,我们可以这样绘制发生的情况。 我们从以P--C
结尾的提交图开始,由branch
指向:
...--P--C <-- branch
当我们进行新提交N
时,我们会得到:
...--P--C--N <-- branch
--amend
时,我们得到以下结果: C
/
...--P--N <-- branch
C
仍然在存储库中;它只是被推到一边,以便新提交 N
可以指向旧的父提交 P
。git commit --amend
后,您意识到想要的是让提交链看起来像这样:...--P--C--N <-- branch
N
;Git永远不会更改存储在仓库中的任何提交(或任何其他对象) - 但请注意,...--P--C
链仍然完整存在。您可以通过reflogs找到提交C
,这就是@{1}
语法所做的事情。(具体来说,这是currentbranch@{1}
的缩写,2意味着“currentbranch
指向一步之前”,即“指向提交C
”)。因此,我们现在运行git reset --soft @{1}
,它会执行以下操作: C <-- branch
/
...--P--N
branch
指向 C
,而 C
又指回 P
。
N
发生了什么? 和 C
之前发生的一样: 它经过 reflog 的保存一段时间。git reset
命令的 --soft
标志保持了索引/暂存区不变 (以及工作树)。这意味着我们现在可以再次创建一个新提交,只需运行另一个 git commit
命令即可。它将经历相同的四个步骤(从 HEAD
中读取 ID、创建树、创建新提交并更新分支): C--N2 <-- branch
/
...--P--N
其中N2
将成为我们的新提交。
我们甚至可以让git commit
重新使用提交N
的提交消息。 git commit
命令有一个--reuse-message
参数,也可以拼写为-C
;我们所要做的就是给它一些信息,让它找到原始的新提交N
,从中复制消息,以此创建N2
。 那么我们该如何做呢? 答案是:它在reflog中,就像我们需要执行git reset
时的C
一样。
事实上,它是同一个@{1}
!
请记住,@{1}
表示“刚才它在哪里”,而git reset
只是更新了它,将其从C
移动到N
。 我们还没有创建新的提交N2
。(一旦我们这样做,N
将变为@{2}
,但我们尚未这样做。)
因此,综合起来,我们得到:
git reset --soft @{1}
git commit -C @{1}
1当你修改合并时,当你处于分离的HEAD状态时,以及当你使用替代索引时,此描述可能会失效。即使在这种情况下,修改描述也是非常明显的。
2如果HEAD
是分离的,那么就没有当前分支,意思变成了HEAD@{1}
。请注意,单独的@
表示HEAD
,因此@{n}
指的是当前分支,而不是HEAD
本身,这有点不一致。
为了看到它们之间的区别,请考虑执行git checkout develop
,然后执行git checkout master
(假设两个分支都存在)。第一个checkout
将HEAD
更改为指向develop
,第二个将HEAD
更改为指向master
。这意味着master@{1}
是最后更新master
之前master
所指向的任何提交;但HEAD@{1}
是develop
现在指向的提交-可能是其他提交。
(总结:在这两个git checkout
命令之后,@{1}
现在表示master@{1}
,HEAD@{1}
表示与develop
现在相同的提交,@
表示HEAD
。如果你感到困惑,那么我也是,显然我不是唯一一个,可以看看评论。)
@{1}
是currentbranch@{1}
的缩写,而不是HEAD@{1}
。 - user4003407HEAD
是符号引用,@{1}
和 @@{1}
仍有不同的含义。 - user4003407@{1}
,因为如果你在git commit --amend
之后做了任何更改,它将不再是1
。如有需要,请运行git reflog
以查找正确的哈希ID或数字以供@{...}
语法使用。 - torek
git reset --soft @{1}
- user4003407git reset --soft @{1}
对我不起作用。我只是恢复了提交,然后压缩它们,解决了这个问题。 - Zhang