1. 理解问题背景

git commit --amend 是一个非常实用的命令,允许我们修改最近一次提交的内容或提交信息。但有时候,我们在 amend 提交后,发现改错了,或者想回到 amend 前的状态。这就引出了一个问题:如何撤销 git commit --amend 操作?

需要注意的是,git commit --amend 并不是在原提交上修改,而是创建了一个全新的提交,替换了原来的提交。虽然我们看到的提交历史中只有一个提交,但实际上原提交已经被 Git 保留为“游离”状态,可以通过 reflog 找回。

2. 演示场景

我们先来看一个具体场景,方便后续操作说明。

假设当前分支(比如 feature1)的提交历史如下:

$ git log
commit 400071c470b8726ba1c749c19cb6d97cff06120c (HEAD -> feature1)
Author: Amanda Viescinski <amanda@example.com>
Date:   Tue Feb 27 11:30:49 2024 -0300

    My original commit message

commit 290896f0e660e38ba8bbbae06670241e7a53eeb0 (origin/main, origin/HEAD, main)
Author: Amanda Viescinski <amanda@example.com>
Date:   Sun Feb 18 17:43:37 2024 -0300

    Initial commit

我们执行了如下 amend 操作:

$ touch script.js
$ git add .
$ git commit --amend -m "My updated commit message"
[feature1 3499867] My updated commit message
 Date: Tue Feb 27 11:30:49 2024 -0300
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 demo.txt
 create mode 100644 script.js

此时查看提交历史:

$ git log
commit 34998671e2b984de80fa67fd795bd3fb61db474d (HEAD -> feature1)
Author: Amanda Viescinski <amanda@example.com>
Date:   Tue Feb 27 11:30:49 2024 -0300

    My updated commit message

commit 290896f0e660e38ba8bbbae06670241e7a53eeb0 (origin/main, origin/HEAD, main)
Author: Amanda Viescinski <amanda@example.com>
Date:   Mon Feb 26 17:43:37 2024 -0300

    Initial commit

可以看到:

  • 提交哈希从 400071c 变成了 3499867
  • 提交信息由 My original commit message 变为 My updated commit message
  • 多了一个 script.js 文件

现在我们想撤销这次 amend,回到 amend 前的状态。

3. 撤销 Git Amend 的方法

3.1 查找原提交记录

我们可以通过 git reflog 查看 HEAD 指针的历史变化:

$ git reflog
3499867 (HEAD -> feature1) HEAD@{0}: commit (amend): My updated commit message
400071c HEAD@{1}: commit: My original commit message
...

其中:

  • HEAD@{0} 是 amend 后的提交
  • HEAD@{1} 是 amend 前的原始提交

因此,我们可以通过重置到 HEAD@{1} 来撤销 amend。

3.2 保留修改内容撤销 amend

如果我们希望撤销 amend,但保留其中的修改内容(比如新增的 script.js),可以使用以下命令:

$ git reset --soft HEAD@{1}

效果如下:

  • 提交历史回到 amend 前的状态
  • 修改内容被保留在暂存区,可以再次提交

验证:

$ git status
On branch feature1
Changes to be committed:
  (use "git restore --staged ..." to unstage)
    new file:   script.js

3.3 删除修改内容撤销 amend

如果我们不仅想撤销 amend,还想彻底删除其中的修改内容,可以使用:

$ git reset --hard HEAD@{1}

效果如下:

  • 提交历史回到 amend 前的状态
  • 所有修改内容都被删除,工作区和暂存区都为空

验证:

$ git status
On branch feature1
nothing to commit, working tree clean

4. 总结

操作 是否保留修改内容 命令
保留修改撤销 amend git reset --soft HEAD@{1}
删除修改撤销 amend git reset --hard HEAD@{1}

📌 小贴士:

  • HEAD@{1} 表示 HEAD 指针在执行 git commit --amend 前指向的提交
  • 使用 git reflog 可以找回被删除或修改的提交
  • --soft--hard 的区别在于是否保留修改内容

推荐做法: 如果不确定是否需要保留修改,建议先使用 --soft 撤销,确认无误后再决定是否提交或删除内容。

⚠️ 注意: 如果你已经将 amend 后的提交推送到远程仓库,撤销操作后需要强制推送(git push -f),这可能会影响其他协作者,请谨慎操作。


原始标题:How to Undo “git commit –amend”