git reset
git reset
git reset 是 Git 中最强大也最容易误用的命令之一。它可以修改分支指针、重置暂存区、甚至擦除工作区的改动。
git reset 用于移动当前分支的 HEAD 到指定位置,并可选择是否同时修改 暂存区(Index) 和 工作区(Working Directory)。
基本语法
git reset [<mode>] <commit>
-
<commit>:你想“重置回去”的目标提交。 -
<mode>:行为模式(默认是--mixed)。
三种主要模式
| 模式 | 作用对象 | HEAD | 暂存区 | 工作区 | 常用语义说明 |
|---|---|---|---|---|---|
--soft |
仅 HEAD | ✅ | ❌ | ❌ | 回退提交但保留所有改动(适合撤销 commit) |
--mixed(默认) |
HEAD + 暂存区 | ✅ | ✅ | ❌ | 回退提交 + 暂存区,但保留工作区(适合撤销 add) |
--hard |
HEAD + 暂存区 + 工作区 | ✅ | ✅ | ✅ | 所有改动回退,慎用(危险) |
示例详解
git reset --soft HEAD~1
撤销最近一次提交,但保留改动(还在暂存区中):
git reset --soft HEAD~1
发现提交错了想重新整理一下 commit 内容,但代码不想动。
git reset --mixed HEAD~1(默认)
撤销最近一次提交 + 暂存区状态也恢复到旧状态,但工作区文件保留。
git reset HEAD~1
想撤销 git commit + git add,重新选择哪些文件要提交。
git reset --hard HEAD~1
彻底回退:提交记录、暂存区、工作区统统恢复到上一个提交状态
git reset --hard HEAD~1
危险操作,未保存的改动会永久丢失。
更通用的 reset 操作
把某个文件从暂存区撤回(等价于 git restore --staged)
git reset HEAD file.cpp
file.cpp改动还在,但不再处于 staged 状态;- 等价于取消了
git add。
指定 commit 回退当前分支
git reset --hard <commit-hash>
可以从 git log 中找出 hash 值,直接重置 HEAD 和分支指针。
git reset 的三块区域图示
+----------------+
| HEAD 指向提交 |
+----------------+
|
v
+-------------+ +--------------+ +---------------+
| 工作目录 | | 暂存区(index)| | 提交历史(HEAD)|
+-------------+ +--------------+ +---------------+
-
--soft:只改 HEAD(左边不变) -
--mixed:改 HEAD 和 暂存区(工作区不变) -
--hard:三者都改
注意事项与常见误解
| 问题 | 解答 |
|---|---|
| reset 会删除提交吗? | 如果没有分支指向旧提交,那些提交就会变为“悬挂提交”(dangling commits),会被 GC 清理 |
| reset 会影响远程吗? | 不会立即影响,但如果你 git push -f,会改变远程历史(慎用) |
| 如何恢复 reset 后丢失的提交? | 有可能用 git reflog 找回 |
误删怎么救回
git reflog
git checkout <原来的 commit 哈希>
或者:
git reset --hard <旧提交>
常用速查表
| 操作目标 | 命令 | 说明 |
|---|---|---|
| 撤销最近一次提交 | git reset --soft HEAD~1 |
保留改动,退回未提交状态 |
撤销提交和 add |
git reset --mixed HEAD~1 |
保留工作区,退回未暂存状态 |
| 强行丢弃所有改动 | git reset --hard HEAD~1 |
工作区也丢弃(危险) |
撤销 git add file |
git reset file |
把文件移出暂存区 |
git reset 和 git revert 区别
| 操作 | 是否修改历史 | 是否适合公开仓库 | 说明 |
|---|---|---|---|
git reset |
✅ 会改历史 | ❌ 不建议 | 本地回退、清理历史 |
git revert |
❌ 不改历史 | ✅ 安全 | 添加一个“反向提交” |

浙公网安备 33010602011771号