如何撤消git提交--修改

如何撤消git提交--修改,git,Git,我不小心输入了一个git commit--amend。这是一个错误,因为我意识到提交实际上是全新的,应该使用新消息提交。我想做出新的承诺。如何撤消此操作?是关键。下面是两个命令序列,用于执行您想要的操作: git reset --soft @{1} git commit -C @{1} 以及如何工作的解释 描述 当您进行新的提交时,Git通常会使用以下事件序列: 读取当前提交的ID(SHA-1散列,如a123456…)(通过HEAD,它为我们提供了当前分支)。让我们将此ID称为C(当前)。请注

我不小心输入了一个git commit--amend。这是一个错误,因为我意识到提交实际上是全新的,应该使用新消息提交。我想做出新的承诺。如何撤消此操作?

是关键。下面是两个命令序列,用于执行您想要的操作:

git reset --soft @{1}
git commit -C @{1}
以及如何工作的解释

描述 当您进行新的提交时,Git通常会使用以下事件序列:

  • 读取当前提交的ID(SHA-1散列,如
    a123456…
    )(通过
    HEAD
    ,它为我们提供了当前分支)。让我们将此ID称为C(当前)。请注意,此当前提交有一个父提交;让我们调用它的ID P(对于父对象)
  • 将索引(也称为临时区域)转换为树。这会产生另一个ID;让我们把这个ID称为T(代表树)
  • 用parent=C和tree=T编写一个新的提交。这个新的提交获得另一个ID。让我们将其称为N(用于new)
  • 使用新的提交ID N更新分支
  • 当使用
    --amend
    Git时,会稍微改变流程。它仍然像以前一样编写新的提交,但在步骤3中,它不是使用parent=C编写新的提交,而是使用parent=P编写新的提交

    图画 从图像上看,我们可以这样画出发生了什么。我们从一个以
    P--C
    结尾的提交图开始,由
    分支
    指向:

    ...--P--C   <-- branch
    
    当我们使用
    --amend
    时,我们得到的是:

           C
          /
    ...--P--N   <-- branch
    
    我们不能完全做到这一点,我们不能改变;Git在repo中存储任何commit(或任何其他对象)后都无法更改它,但请注意,
    ..--P--C
    链仍然在那里,完全完好无损。您可以通过reflogs找到commit
    C
    ,这就是
    @{1}
    语法的作用。(具体来说,这是
    currentbranch@{1}
    ,2的缩写,意思是“其中
    currentbranch
    在一步之前指向了”,即“提交
    C

    因此,我们现在运行
    git reset--soft@{1}
    ,它可以:

           C   <-- branch
          /
    ...--P--N
    
    其中,
    N2
    将是我们的新(第二个新?)提交

    我们甚至可以通过commit
    N
    重新使用commit的提交消息。
    git commit
    命令有一个
    --reuse message
    参数,也拼写为
    -C
    ;我们所要做的就是给它一些东西,让它找到原始的新提交
    N
    ,从中复制消息,并使用
    N2
    。我们怎么做?答案是:它在reflog中,就像我们需要执行git重置时的
    C
    一样

    事实上,这是相同的
    @{1}

    记住,
    @{1}
    的意思是“它刚才在哪里”,而
    git reset
    刚刚更新了它,将它从
    C
    移动到
    N
    。我们尚未进行新的提交
    N2
    。(一旦我们这样做,
    N
    将成为
    @{2}
    ,但我们还没有做到。)

    因此,综合起来,我们得到:

    git reset --soft @{1}
    git commit -C @{1}
    

    1此描述的细分位置包括修改合并时、位于分离的头部时以及使用替代索引时。尽管如此,如何修改描述还是很明显的

    2如果
    HEAD
    被分离,因此没有当前分支,则含义变为
    HEAD@{1}
    。请注意,
    @
    本身是
    HEAD
    的缩写,因此
    @{n}
    引用当前分支而不是
    HEAD
    本身的事实有点不一致

    看看它们是如何不同的,请考虑<代码> Git签出开发后面跟着“代码> Git签出主< /代码>(假设两个分支都存在)。第一个

    签出
    更改
    指向
    开发
    ,第二个更改
    指向
    。这意味着
    master@{1}
    是上次更新
    master
    之前提交
    master
    所指向的内容;但是
    HEAD@{1}
    是提交
    develope
    指向现在可能是其他提交的


    (重述:在这两个
    git checkout
    命令之后,
    {1}
    意味着
    master{1}
    现在,
    HEAD{1}
    意味着与
    develope
    现在相同的提交,而
    意味着
    HEAD
    。如果你感到困惑,那么,我也是,显然我并不孤单:请参阅注释。)

    git reset--soft
    git reset--soft@{1}
    对我不起作用。我只是恢复提交,然后挤压它们。解决了这个问题。
    {1}
    当前分支{1}
    的缩写,而不是
    头{1}
    @PetSerAl:啊哈,你说得对!虽然如果HEAD被分离,它将作为
    HEAD@{1}
    工作。这似乎有点不一致,因为
    @
    意味着
    ,但我认为
    头{0}
    当前分支{0}
    必须是同义词,如果存在当前分支的话。谢谢,我会解决这个问题。@andrybak:通过移动
    头部和/或一些分支几次,分离头部,再移动一些,然后重新连接来测试它。语义比语法更复杂。@andrybak即使是
    HEAD
    也是符号ref,
    {1}
    {1}
    有不同的含义。@8bit瘾君子:不要盲目地使用
    {1}
    ,因为如果你在
    git提交--amend
    之后做了任何事情,它就不再是
    1
    。如果需要,运行
    git reflog
    ,为
    @{…}
    语法找到正确的哈希ID或数字。
           C   <-- branch
          /
    ...--P--N
    
           C--N2   <-- branch
          /
    ...--P--N
    
    git reset --soft @{1}
    git commit -C @{1}