我不小心输入了一个git commit --amend.这是一个错误,因为我意识到提交实际上是全新的,它应该用新消息提交.我想做一个新的提交.我该如何撤消这个?
tor*_*rek 107
PetSerAl的评论是关键.这是两个命令序列,可以满足您的需求:
git reset --soft @{1}
git commit -C @{1}
Run Code Online (Sandbox Code Playgroud)
并解释这是如何工作的.
当你犯了一个新的提交,Git的通常1使用事件的顺序:
a123456...
当前提交的ID(SHA-1哈希等)(via HEAD
,它为我们提供当前分支).我们称这个ID为C(对于当前).请注意,此当前提交具有父提交; 让我们称它为ID P(对于Parent).使用--amend
Git时会稍微改变一下这个过程.它仍然像以前一样写一个新的提交,但是在步骤3中,它不是用parent = C写新的提交,而是用parent = P写它.
从图像上看,我们可以画出这种方式.我们从一个以下结尾的提交图开始P--C
,指向branch
:
...--P--C <-- branch
Run Code Online (Sandbox Code Playgroud)
当我们进行新的提交时,N
我们得到:
...--P--C--N <-- branch
Run Code Online (Sandbox Code Playgroud)
当我们使用时--amend
,我们得到这个:
C
/
...--P--N <-- branch
Run Code Online (Sandbox Code Playgroud)
需要注意的是承诺C
是仍然在仓库中 ; 它只是被推到一边,一路走开,所以新的提交N
可以指向旧的父母P
.
在你之后你意识到你想要git commit --amend
的链条看起来像是:
...--P--C--N <-- branch
Run Code Online (Sandbox Code Playgroud)
我们不能相当做到这一点,我们不能改变N
; 一旦存储在repo中,Git永远不会更改任何提交(或任何其他对象),但请注意...--P--C
链仍然在那里,完整无缺.您可以C
通过reflog 找到提交,这就是@{1}
语法的作用.(具体来说,这是2的缩写currentbranch@{1}
,意思是" 前一步指向",即"提交".)currentbranch
C
所以,我们现在运行git reset --soft @{1}
,这样做:
C <-- branch
/
...--P--N
Run Code Online (Sandbox Code Playgroud)
现在branch
指向C
,指向回到P
.
怎么了N
?C
之前发生过同样的事情:它通过reflog保存了一段时间.
我们并不真的需要它(尽管它可能会派上用场),因为保持索引/暂存区域的--soft
标志git reset
不受影响(与工作树一起).这意味着我们现在可以通过运行另一个来再次进行新的提交git commit
.它将经历相同的四个步骤(从中读取ID HEAD
,创建树,创建新提交,并更新分支):
C--N2 <-- branch
/
...--P--N
Run Code Online (Sandbox Code Playgroud)
N2
我们新的(第二个新的?)提交将在哪里.
我们甚至可以git commit
从提交中重用提交消息N
.该git commit
命令有一个--reuse-message
参数,也是拼写的-C
; 我们所要做的就是给它一些东西,让它找到原始的新提交N
,从中复制消息N2
.我们怎么做?答案是:它在reflog中,就像C
我们需要做的那样git reset
.
事实上,它是一样的@{1}
!
请记住,@{1}
意思是"刚才的地方",并且git reset
只是更新它,将其C
移至N
.我们还没有做出新的承诺N2
.(一旦我们这样做,N
将会@{2}
,但我们还没有.)
所以,把它们放在一起,我们得到:
git reset --soft @{1}
git commit -C @{1}
Run Code Online (Sandbox Code Playgroud)
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
.如果你感到困惑,那么我也是,显然我并不孤单:看到评论.)
归档时间: |
|
查看次数: |
26118 次 |
最近记录: |