- 想撤回提交、取消暂存或回到旧位置的人
Command Reference
git reset 教程
解释 git reset 如何移动 HEAD、分支和暂存区,并区分 --soft、--mixed、--hard 的影响范围。
- 知道 HEAD、暂存区、工作区是三层
- 能接受先建救援分支再操作
- 误用 `--hard` 覆盖工作区
- 没确认共享边界就移动历史
一句话理解
git reset 的本质是移动当前引用,并按模式决定是否同步更新暂存区和工作区。
先记住三个层次
- 提交历史
- 暂存区
- 工作区
理解 reset 的关键,就是看它影响到哪一层。
这张图可以当成一个最快速的判断器:只要你准备动 --hard,就等于你允许工作区也被覆盖,那就应该先停一下,确认恢复路径。
三种最常见模式
--soft
只移动提交引用,不改暂存区和工作区。
--mixed
移动提交引用,并重置暂存区,但保留工作区改动。默认模式通常就是它。
--hard
同时移动提交引用、重置暂存区、覆盖工作区改动。风险最高。
用三层模型重新理解 reset
你可以把 reset 的行为拆成三问:
- 当前分支 / HEAD 要不要移动
- 暂存区要不要跟着目标提交重置
- 工作区文件要不要也被覆盖
这三问基本就对应了 soft、mixed、hard 的差别。
最常见的三类用途
1. 撤回提交但保留改动
git reset --soft HEAD~1
2. 取消暂存
git reset HEAD path/to/file
3. 彻底回退到某个安全点
git reset --hard <commit>
一个更稳的操作顺序
当你准备做可能破坏当前状态的 reset 时,推荐顺序是:
git statusgit log --oneline --decorate -5git reflog- 如有必要先建救援分支
- 再执行 reset
比如:
git branch backup/before-reset
git reset --hard HEAD~1
如果你对 hard reset 还有点没底,可以把它和图里的第三列对照一下看。只要你发现自己真正想要的是“撤销提交但保留文件改动”,那通常就不该走 --hard。
基本示例
撤回最近一次提交,但保留改动待重新提交
git reset --soft HEAD~1
取消暂存,但保留工作区内容
git reset HEAD path/to/file
彻底回到某个提交
git reset --hard <commit>
reset、restore、revert 的区别
reset:移动当前引用,可能影响暂存区和工作区restore:更偏向恢复文件内容revert:通过新增一个“反向提交”来撤销历史
团队协作里,如果改动已经发布给别人,通常要优先考虑 revert,而不是直接 reset 已共享历史。
git reset HEAD <file> 为什么常被新手搞混
因为它看起来像是在“回退文件”,但更准确地说,它主要是在把文件从暂存区拿出来,让工作区继续保留改动。
什么时候要特别小心
- 你不确定当前分支是不是共享分支
- 你还没有确认 reflog 可恢复路径
- 工作区里还有未保存的重要改动
尤其是下面两种情况:
- 你正在公共分支上
- 你不确定这次 reset 之后还需不需要保留部分改动
reset 与 restore 的关系
现代 Git 把一部分“工作区 / 暂存区恢复”语义拆给了 git restore,但 reset 仍然是理解 Git 引用移动的关键命令。
常见误区
误区 1:reset 就是删除提交
不准确。很多时候它只是让当前引用不再指向那些提交,对象本身未必立刻消失。
误区 2:--hard 只是更快一点
不是。它会真正覆盖工作区内容,风险性质完全不同。
误区 3:reset 之后提交就永久没了
很多时候不是。只要旧提交还在 reflog 或仍然可达,就通常还有恢复空间。
安全建议
执行破坏性 reset 前,先做至少一件事:
git statusgit reflog- 建一个救援分支
一个实战判断原则
如果你的目标是:
- 重新整理本地未共享提交:可以考虑 reset
- 撤销已经共享给团队的历史:优先考虑 revert
- 只想恢复文件内容:优先考虑 restore
这条命令在流程里解决什么问题
git reset 直接影响历史表达、引用位置或提交之间的关系。读这类命令时,要先判断这次操作是在整理本地未共享历史,还是在处理已经公开给团队的历史。
典型用例
- 在合并、回滚、挑提交或整理提交序列时,用
git reset重塑历史表达。 - 把
git reset放进“先备份、再变更、最后复核”的高风险操作流程,降低误操作损失。 - 在复盘冲突、回滚事故或判断分支关系时,用
git reset理清提交之间的因果链。
图例理解
特殊情况与边界
- 历史类命令最常见的风险,是对已经共享出去的提交继续做重写或移动。
- 如果这次操作可能影响团队协作,先跑
git status、git log --oneline --graph和git reflog,再决定是否继续。 - 一旦不确定,就先建一个备份分支,让自己保留“能回去”的选项。
- 只要涉及
--hard,就应该先确认工作区里有没有还没备份的重要改动。
跟着做一遍
这一组练习最重要的是观察 HEAD、暂存区和工作区分别发生了什么,而不是只记住参数名字。
git switch -c lab/reset-demo # 连续做两次提交 # 再额外修改一个文件并执行 git add跟着做
- 先运行 `git reset --soft HEAD~1` 并观察 `git status`。
- 再重复实验,改用 `git reset --mixed HEAD~1`。
- 最后只在实验仓库中试一次 `git reset --hard HEAD~1`。
- `--soft` 会保留暂存区和工作区内容。
- `--mixed` 会把暂存内容退回工作区。
- `--hard` 会让 HEAD、暂存区和工作区一起回到目标提交。
- 如果你真正想要的是撤回提交但保留改动,通常不该直接选 `--hard`。
- 如果旧提交已经共享给团队,应该优先评估 `revert`,而不是直接 reset 共享历史。
- 只要你不确定恢复路径,先跑 `git reflog` 再继续。
继续学习建议
接下来建议继续补:
git refloggit restoregit revert