(九)撤销、修正与找回提交
1. 先确定要改变哪个位置
同样叫“撤销”,可能只是取消暂存,也可能要生成一个反向提交。对照前面的三处内容来选择:
| 当前动作 | 命令 | 执行后的内容 |
|---|---|---|
| 文件暂存多了,仍要继续编辑 | git restore --staged -- README.md |
暂存区回到 HEAD,工作目录的编辑保留 |
| 刚才的未暂存编辑不要了 | git restore --worktree -- README.md |
工作目录被暂存区内容替换 |
| 从历史中取回某份文件 | git restore --source=HEAD~1 --worktree -- README.md |
工作目录取得指定提交中的文件,需重新检查和暂存 |
| 本地最后一次提交漏了一处改动 | git commit --amend --no-edit |
用当前暂存内容修订最后一次提交,生成新的提交标识 |
| 退回一次本地提交,重新安排提交内容 | git reset --soft HEAD~1 |
分支退到父提交,原文件和暂存内容保留 |
| 已分享的一项普通提交需要撤销 | git revert 提交哈希 |
在当前历史后追加反向修改,原提交仍保留 |
先运行 git status、git diff 与 git diff --cached,看清本次操作会以哪份内容替换哪一份。restore --worktree 会覆盖选定文件的未暂存修改;Git 尚未保存过的文本,需要从编辑器本地历史或其他副本中寻找。
2. 用反向提交保留已经分享的历史
假设误把 README 中的目标改成 350,提交后已经分享。记录这次提交的哈希,运行 git revert 该哈希,Git 会把对应的反向变化追加到当前分支。对本例这样的一次普通提交,可以直接观察 350 → 35;后续又修改过相同位置时,反向变化也可能需要解决冲突。
amend 与 reset 改变的是本地分支所指向的提交历史;已经推送的旧提交可能已被同伴作为继续工作的起点。让他们直接取得新的反向提交,比要求他们重新接续一条被改写的历史更容易协作。revert、reset
3. 从本地引用记录找到原来的位置
在练习分支中进行一次 reset --soft HEAD~1 后,原来的提交不再被该分支指向,但本地 reflog 记录了 HEAD 刚才的移动:
# 查看本机 HEAD 的近期移动,找到刚才离开的提交。
git reflog -6
# 紧接着上述一次 reset 时,前一个位置就是刚才的提交;引号兼容 PowerShell。
git branch rescue-before-reset "HEAD@{1}"
git show --stat rescue-before-reset
给旧位置建立 rescue-before-reset 后,可以先检查,再决定合并、取文件或切换过去。reflog 是本机引用的移动记录,会过期,也不会把从未进入 Git 的所有编辑都保存下来。reflog