如何撤消"git commit --amend"而不是"git commit"

Jes*_*sen 1198 git commit undo git-amend

我不小心修改了我以前的提交.提交应该是独立的,以保留我对特定文件所做更改的历史记录.

有没有办法撤消最后一次提交?如果我这样做git reset --hard HEAD^,第一次提交也会撤消.

(我还没有推到任何远程目录)

CB *_*ley 2095

您需要做的是创建一个新提交,其具有与当前HEAD提交相同的详细信息,但父项为先前版本HEAD.git reset --soft将移动分支指针,以便下一次提交发生在当前分支头现在的不同提交之上.

# Move the current head so that it's pointing at the old commit
# Leave the index intact for redoing the commit.
# HEAD@{1} gives you "the commit that HEAD pointed at before 
# it was moved to where it currently points at". Note that this is
# different from HEAD~1, which gives you "the commit that is the
# parent node of the commit that HEAD is currently pointing to."
git reset --soft HEAD@{1}

# commit the current tree using the commit details of the previous
# HEAD commit. (Note that HEAD@{1} is pointing somewhere different from the
# previous command. It's now pointing at the erroneously amended commit.)
git commit -C HEAD@{1}
Run Code Online (Sandbox Code Playgroud)

  • 为了清楚起见,第一个命令是一个真正的"撤消".它在`git commit --amend`之前生成HEAD,工作目录(未更改)和索引状态.第二个是对新提交的"重做".这些适用于任何`git commit`,而不仅仅是`--amend`. (168认同)
  • 因此,如果您没有使用需要抢救的新提交消息进行修改,则第二部分可以是常规的`git commit`. (57认同)
  • 非常酷,+ 1.我甚至用第二个修改视图到`git reflog`来找到正确的数字,例如`{2}`. (28认同)
  • @TimArnold取决于你的shell,你可能需要在`HEAD @ {1}`周围加上单引号或双引号.例如,如果我在tcsh中运行`echo HEAD @ {1}`,则输出为`HEAD @ 1`,因为大括号由tcsh解释.如果我使用单引号,则会保留大括号. (20认同)
  • 出于某种原因,我在运行`git reset --soft HEAD @ {1}时遇到错误:`fatal:ambiguous argument'HEAD @ 1':未知修订版或路径不在工作树中.使用' - '将路径与修订版本分开.当我用`git reflog`中显示的等效提交哈希替换`HEAD @ {1}`时(感谢JJD!),这个答案非常有用! (18认同)
  • 做`git reflog`会显示你已经完成的事情列表 - 如果你做了一些其他的事情,因为'修改'有帮助 - "HEAD @ {1}"指的是最近的行动 (4认同)
  • @demisx:不,`HEAD @ {1}`和`HEAD ^ 1`不一样.理解`HEAD @ {1}`和`reflog`是解决方案的关键所在.比较`HEAD @ {1}`引用VS的`git reflog`.`git log``HEAD ^ 1`引用的提交历史.实际上,reflog实际上要简单得多(因为它是线性的,或者至少是它的引用),而提交历史可能是树状的,具有更复杂的引用.如果你想深入了解那个兔子洞的结帐`HEAD~`vs`HEAD ^`:http://stackoverflow.com/questions/2221658/whats-the-difference-between-head-and-head-in-git (3认同)
  • 第一行救了我的命(git reset --soft HEAD@{1} 来撤消提交 --amend)。谢谢! (2认同)
  • 跟进“git commit --amend --reset-author”将提交的作者设置为您自己可能会有所帮助。就我而言,我错误地修改了作者 A 的最后一次提交,并且当如上所述重置和提交时,我的提交的作者仍然是 A。 (2认同)

kni*_*ttl 125

使用ref-log:

git branch fixing-things HEAD@{1}
git reset fixing-things
Run Code Online (Sandbox Code Playgroud)

然后,您应该只在您的工作副本中进行所有先前修改的更改,并且可以再次提交

查看以前索引类型的完整列表 git reflog

  • @neaumusic:是的!`HEAD~1`与`HEAD ^`完全相同,标识当前提交的_parent_.另一方面,`HEAD @ {1}`指的是HEAD在此之前指向的提交,即当你签出不同的分支或修改提交时它们意味着不同的提交. (14认同)
  • 这也擦除了索引 - 仍然有用,但超出了简单的"撤消". (7认同)
  • 第一步是多余的.简单的`git reset HEAD @ {1}`就足够了. (7认同)
  • 哇,“reflog”的意思是“ref-log”而不是“re-flog”?这更有意义 (6认同)
  • 在'HEAD @ {1}`和`HEAD~1`之间有什么区别吗? (3认同)

ken*_*orb 64

通过以下方式查找修改的提交:

git log --reflog
Run Code Online (Sandbox Code Playgroud)

注意:--patch为了清楚起见,您可以添加以查看提交的正文.与...相同git reflog.

然后将HEAD重置为任何先前的提交,只需通过以下方式:

git reset SHA1 --hard
Run Code Online (Sandbox Code Playgroud)

注意: SHA1 替换为您的实际提交哈希.另请注意,此命令将丢失所有未提交的更改,因此您可以先将其存储.或者,使用--soft保留最新更改然后提交它们.

然后樱桃挑选你需要的其他提交:

git cherry-pick SHA1
Run Code Online (Sandbox Code Playgroud)

  • 如果你执行`git reset SHA1 --soft`,你可以保留最新的更改,然后提交它们. (24认同)

Ois*_*ley 33

使用 的这些答案都不HEAD@{1}适合我,所以这是我的解决方案:

git reflog

d0c9f22 HEAD@{0}: commit (amend): [Feature] - ABC Commit Description 
c296452 HEAD@{1}: commit: [Feature] - ABC Commit Description 
Run Code Online (Sandbox Code Playgroud)

git reset --soft c296452

您的临时环境现在将包含您不小心与 c296452 提交合并的所有更改。

  • 我在已经推送的提交上执行了“git commit --amend”,因此其他建议不起作用。但这确实做到了。谢谢。 (11认同)
  • 如果您使用的是 powershell,`git reset --soft "HEAD@{1}"` 需要包含引号。`{1}` 看起来是特殊语法 (3认同)

Ark*_*nez 24

您始终可以从手册中拆分提交

  • 使用git rebase -i commit ^启动交互式rebase,其中commit是要拆分的提交.实际上,只要包含该提交,任何提交范围都可以.
  • 使用"编辑"操作标记要拆分的提交.
  • 在编辑提交时,执行git reset HEAD ^.结果是HEAD被一个重绕,索引也随之而来.但是,工作树保持不变.
  • 现在将更改添加到您希望在第一次提交中拥有的索引.您可以使用git add(可能是交互式)或git-gui(或两者)来做到这一点.
  • 使用现在适当的提交消息提交now-current索引.
  • 重复最后两步,直到工作树干净.
  • 用git rebase继续rebase - 继续.

  • 太复杂了.`git reflog`就是你所需要的 (24认同)
  • 另外,这个答案允许你有选择地选择你不小心"修改"的变化,为git reset提供一些额外的价值--soft HEAD @ {1}方法(确实解决了我的问题BTW) (5认同)
  • 有很多步骤,但每个步骤都很简单,很容易做到.这对我有用,并得到我的投票. (2认同)
  • 您也可以使用reflog方法选择性地选择更改.只需要`git reset`而不是`git reset --soft`,然后执行`git add --patch`. (2认同)
  • 这仍然会改写历史,需要强制推动。根据您的情况,这可能是也可能不是问题。 (2认同)

小智 16

可能值得注意的是,如果您仍然在编辑器中使用提交消息,则可以删除提交消息,它将中止git commit --amend命令.


utz*_*coz 14

也许可以git reflog在修改之前和修改之后使用两次提交.

然后用于git diff before_commit_id after_commit_id > d.diff在修改之前和修改之后获得差异.

接下来用于git checkout before_commit_id在提交之前返回

最后用于git apply d.diff应用你所做的真正改变.

这解决了我的问题.


小智 10

您可以执行以下操作来撤消您的 git commit —amend

  1. git reset --soft HEAD^
  2. git checkout files_from_old_commit_on_branch
  3. git pull origin your_branch_name

====================================

现在您的更改与以前一样。所以你完成了撤销git commit —amend

现在您可以执行git push origin <your_branch_name>, 推送到分支。


gar*_*mac 7

差不多晚了 9 年,但没有看到提到的这种变化可以完成同样的事情(它是其中一些的组合,类似于顶级答案(/sf/answers/102148511/) .

搜索分支上的所有分离头

git reflog show origin/BRANCH_NAME --date=relative

然后找到SHA1哈希

重置为旧的 SHA1

git reset --hard SHA1

然后再向上推。

git push origin BRANCH_NAME

完毕。

这将使您完全恢复到旧提交。

(包括之前覆盖的分离提交头的日期)

  • 是的,但我通常想重置 `--soft` 以保留我的更改。我只是希望它单独提交 (4认同)

Dav*_*pko 6

如果您已将提交推送到远程,然后错误地修改了该提交的更改,则可以解决您的问题。发出a git log在提交之前找到SHA。(这假设远程被命名为origin)。现在,使用该SHA发出这些命令。

git reset --soft <SHA BEFORE THE AMMEND>
#you now see all the changes in the commit and the amend undone

#save ALL the changes to the stash
git stash

git pull origin <your-branch> --ff-only
#if you issue git log you can see that you have the commit you didn't want to amend

git stash pop
#git status reveals only the changes you incorrectly amended

#now you can create your new unamended commit
Run Code Online (Sandbox Code Playgroud)

  • 这是比较笼统的问题的特例,但恰好满足了我的迫切需求。 (2认同)