Git 撤销与回退:restore / reset / revert / clean
更新时间:2026-08-25。本篇覆盖撤销类命令:
git restore(恢复文件)、git reset(移动 HEAD)、git revert(反向提交)、git clean(清理未跟踪)。撤销的本质是"让某个区域回到某个快照"。
撤销的本质:四个区域回退

1. git restore:恢复文件(安全,默认不动历史)
bash
git restore <file> # 丢弃工作区改动,回到暂存区/HEAD 版本(危险!)
git restore --staged <file> # 取消暂存(保留工作区改动)← 最常用
git restore --source=<commit> <file> # 从指定提交恢复文件对照 status-add-commit 的状态提示:
bash
$ git status
Changes not staged: # 工作区有改动 → git restore <file>
Changes to be committed: # 已暂存 → git restore --staged <file>
git restore <file>会永久丢失工作区未提交的改动,执行前确认没有保存价值。
2. git reset:移动 HEAD 指针(会改写历史)
bash
git reset --soft HEAD~1 # HEAD 回退,暂存区保留(改动已暂存)
git reset --mixed HEAD~1 # HEAD 回退,暂存区清空,工作区保留(默认)
git reset --hard HEAD~1 # HEAD 回退,暂存区+工作区全部丢弃(危险!)
git reset <commit> # 默认 --mixed| 模式 | HEAD | 暂存区 | 工作区 | 用途 |
|---|---|---|---|---|
--soft | 移动 | 保留 | 保留 | 合并多个提交(配合 commit 重做) |
--mixed | 移动 | 清空 | 保留 | 撤销"已暂存"但保留改动重新 add |
--hard | 移动 | 清空 | 清空 | 彻底回退到某个提交 |
示例:撤销最后一次提交但保留改动
bash
git reset --soft HEAD~1 # 提交被撤销,改动回到暂存区
git reset HEAD~1 # 或 --mixed:改动回到工作区(未暂存)
--hard是数据销毁命令:git reset --hard丢弃的提交若不在 reflog 中即无法找回(reflog 通常保留 90 天,见 标签与排障)。
3. git revert:反向提交(安全,不改历史)
bash
git revert <commit> # 生成一个"撤销该提交"的新提交
git revert HEAD # 撤销最近一次提交
git revert --no-commit <commit> # 只暂存反向改动,不自动提交(可合并多个)与 reset 的本质区别:
| 维度 | git reset | git revert |
|---|---|---|
| 历史形态 | 删除/改写提交 | 追加反向提交 |
| 是否改写历史 | 是 | 否 |
| 已推送后可用 | ❌ 会与他人冲突 | ✅ 安全 |
| 适用 | 本地未推送的提交 | 已推送的提交、线上回滚 |
线上回滚一律用
revert:reset --hard+force push会破坏共享历史,而revert只是加一个"撤销提交",历史完整、他人拉取无冲突。
4. git clean:清理未跟踪文件
bash
git clean -n # 预览将被删除的文件(-n 干跑,先看再删!)
git clean -f # 删除未跟踪文件
git clean -fd # 连同未跟踪目录一起删
git clean -nd # 预览含目录
git clean不处理.gitignore忽略的文件(除非加-x)。它是唯一能批量删除未跟踪文件的命令,务必先-n预览。
撤销场景对照表
| 我想… | 命令 | 是否改写历史 |
|---|---|---|
| 丢弃工作区单个文件的改动 | git restore <file> | 否 |
| 取消暂存(保留改动) | git restore --staged <file> | 否 |
| 撤销最近提交、保留改动 | git reset --soft HEAD~1 | 是 |
| 彻底回退到某提交 | git reset --hard <commit> | 是(慎用) |
| 撤销已推送的提交 | git revert <commit> | 否(新增提交) |
| 删掉未跟踪文件/目录 | git clean -fd | 否(直接删) |
| 误删/误 reset 想找回 | git reflog → git reset --hard | 恢复 |
易错点
reset --hard与revert混淆:本地随手写可用 reset;已推送 / 线上必须 revert。restore与reset命令参数混淆:restore后面跟路径,reset后面跟提交。clean -f前不预览:clean删除的文件不经过 reflog,不可找回——永远先-n。revert多个提交的顺序:从旧到新逐个 revert(或--no-commit累积后一次提交),避免反向依赖冲突。
一句话总结:按"是否已推送"选择——本地未推送用 reset/restore(改写历史),已推送用 revert(追加反向提交);一切破坏性操作前先 status/clean -n/stash 确认现场。