四种情况,四条命令。在下面找到和你处境相同的那一句,复制它下面的命令。第零条规则:已经推送了?用 revert。其余方法都假设这个提交还只在本地。
🎙️ 发布并录制于: ·
如果提交还在本地,先决定它带的那些文件该怎么办。soft reset 只撤掉提交,所有修改留在暂存区,所以当你打算重新提交时,它是正确的默认选择。hard reset 撤掉提交,还会把工作区文件变回上一个快照的样子。别只因为“撤销”这个词听起来干脆,就顺手用了 hard reset。
# "Undo the commit, KEEP my changes" — most common:
git reset --soft HEAD~1
# "Undo the commit AND throw away the changes":
git reset --hard HEAD~1
# Last N commits, with all changes staged as one pile:
git reset --soft HEAD~3
fatal: ambiguous argument 'HEAD~1': unknown revision or path not in the working tree.运行 git log --oneline。如果只显示一个提交,那就没有更早的快照可以给 reset 当目标。文件先留着,如果你真的需要一段全新历史,就建一个孤立分支,否则直接修订这第一个提交。多敲几个波浪号,造不出一个不存在的父提交。
amend 会用一个改好的提交替换掉最新那一个。提交说明里有错字,或者忘了暂存某个文件,用它。提交哈希会变,所以只有这个提交还属于你、还没推出去的时候,amend 才算干净。如果队友可能已经拿到了旧哈希,那就新建一个提交。
# The content is right; only the message is wrong:
git commit --amend -m "the message I meant to write"
# Add a forgotten file without changing the message:
git add forgotten.py
git commit --amend --no-edit
fatal: You have nothing to amend.看一下 git log --oneline。你要么在一个还没有任何提交的仓库里,要么在一个尚未诞生的分支上。先把文件暂存,正常做出第一个提交;只有 HEAD 已经指向某个提交时,amend 才有效。
revert 会读取一个已有的提交,再造一个做相反改动的新提交。这样公开历史保持完整,已经拉过代码的队友也不用去修自己的分支。在共享分支上,我宁愿去解释一个不好看的 revert 提交,也不想解释为什么强制推送之后某人的工作不见了。
git revert HEAD
# creates a new commit that cancels the latest one; then push it
git revert abc1234
# same operation for an older commit by hash
error: could not revert abc1234... Remove broken validationhint: after resolving the conflicts, mark the corrected paths with 'git add <paths>'运行 git status,打开每个未合并的文件,留下你希望 revert 之后代码呈现的那个版本,删掉冲突标记,然后对每个文件运行 git add,再执行 git revert --continue。想放弃这次操作、回到 revert 之前的状态,运行 git revert --abort。
hard reset 移动的是分支标签,Git 通常还留着那个旧的提交对象。reflog 记录了 HEAD 曾经指向过哪些地方。先读这些记录,找出 reset 之前的那个提交,必要时先看一眼它的内容,然后才往回走。别默认上一条记录就一定是你要的那个,别的命令可能又写进了更新的 reflog 记录。
git reflog
# a1b2c3d HEAD@{0}: reset: moving to HEAD~1
# f4e5d6c HEAD@{1}: commit: the one you want back
git show f4e5d6c # inspect before moving anything
git reset --hard f4e5d6c # restore that exact commit
# equivalent here: git reset --hard HEAD@{1}
reset --soft HEAD~1 · 丢弃修改:reset --hard HEAD~1 · 改最新那个提交:--amend · 已经推送:revert HEAD · 找回来:reflog。