CLI AI

撤销上一次 git 提交但保留改动

2026-05-10

git reset --soft HEAD~1 会移除该提交,并把所有改动重新放回暂存区,和提交前那一刻完全一样。这是常见情况下的答案。你处于哪种情况,比用哪个参数更重要。

1. 还没 push——撤销提交,保留暂存的改动

clai
$ clai 撤销我的上一次提交,但把改动保留在暂存区→ git reset --soft HEAD~1$ git status --shortM  f.txt

提交从日志中消失了,文件没有被改动,所有内容仍在暂存区。修正提交信息,或者把漏掉的文件加进来,然后重新提交。

2. 保留改动,但取消暂存

clai
$ clai 撤销上一次提交,并把改动也从暂存区移除→ git reset HEAD~1

--mixed 是默认模式。和 soft 一样,只是多退一步:文件留在磁盘上,暂存区被清空。想把改动重新拆分成不同的提交时用它。

3. 彻底丢弃这些改动

clai
$ clai 永久删除我的上一次提交及其所有改动→ git reset --hard HEAD~1⚠ DANGER — uncommitted changes in the working tree are destroyed

--hard 是三者中唯一会丢失工作内容的。已提交的内容可以通过 reflog 找回;而已修改但未提交的内容则不行。

4. 已经 push 过——用 revert 而不是 reset

clai
$ clai 撤销我已经 push 过的提交,但不要改写历史→ git revert HEAD

revert 会创建一个新提交来撤销旧提交。历史保持不变,任何已经拉取过的人都不需要做任何事。在共享分支上,这是唯一正确的做法。

5. 只是想改一下提交信息

clai
$ clai 修改我上一次提交的信息→ git commit --amend -m "Fix cache invalidation on write path"

如果暂存区是空的,--amend 只会重写提交信息。如果暂存区有内容,它也会把这些改动合并进上一次提交——很有用,但也容易不小心触发。

6. 选错了——把它找回来

clai
$ clai 告诉我这次 reset 之前 HEAD 在哪里→ git reflog4d2e830 HEAD@{0}: reset: moving to HEAD~1dc4fa62 HEAD@{1}: commit: second4d2e830 HEAD@{2}: commit (initial): first$ git reset --hard dc4fa62

reflog 默认会记住 HEAD 90 天内所在过的每一个位置。对一个丢失的提交执行 --hard reset,可以把它原样找回来。

常见陷阱

  • 永远不要对共享分支强制推送 reset。 改写别人已经拉取过的历史,会破坏他们本地的克隆。这正是 revert 存在的意义。
  • 这里的 HEAD~1 和 HEAD^ 是同一个东西——都是回退一个提交。它们只在合并提交上才有区别,此时 HEAD^2 指第二个父提交。
  • push 之后再用 --amend 同样会改写历史。 它会创建一个哈希值不同的新提交对象,所以同样的规则适用。

相关问题

如何撤销最近三次提交,同时保留所有改动? git reset --soft HEAD~3——这几次提交里的改动会一起进入暂存区。

reset 会永久删除提交吗? 不会立刻删除。它会变得不可达,但 reflog 默认还会指向它大约 90 天,直到垃圾回收运行。

在没有其他人使用的功能分支上,该用 reset 还是 revert? 用 reset,更干净。一旦可能有别人拉取过,就改用 revert。

相关阅读

CliAI 把 reset --hard 标记为 DANGER,并要求手动输入确认——这是唯一真正会丢失工作内容的 git 命令。一行命令安装。