Command Reference

git reset 教程

解释 git reset 如何移动 HEAD、分支和暂存区,并区分 --soft、--mixed、--hard 的影响范围。

适合谁看
  • 想撤回提交、取消暂存或回到旧位置的人
前置知识
  • 知道 HEAD、暂存区、工作区是三层
  • 能接受先建救援分支再操作
常见风险
  • 误用 `--hard` 覆盖工作区
  • 没确认共享边界就移动历史

一句话理解

git reset 的本质是移动当前引用,并按模式决定是否同步更新暂存区和工作区。

先记住三个层次

  1. 提交历史
  2. 暂存区
  3. 工作区

理解 reset 的关键,就是看它影响到哪一层。

reset 的三层影响不管 soft、mixed 还是 hard,都会先移动 HEAD。区别在于暂存区和工作区是否继续跟着目标提交一起重置。
影响层--soft--mixed--hard
HEADMovesMovesMoves
IndexKeepsResetsResets
WorktreeKeepsKeepsOverwrites

这张图可以当成一个最快速的判断器:只要你准备动 --hard,就等于你允许工作区也被覆盖,那就应该先停一下,确认恢复路径。

三种最常见模式

--soft

只移动提交引用,不改暂存区和工作区。

--mixed

移动提交引用,并重置暂存区,但保留工作区改动。默认模式通常就是它。

--hard

同时移动提交引用、重置暂存区、覆盖工作区改动。风险最高。

用三层模型重新理解 reset

你可以把 reset 的行为拆成三问:

  1. 当前分支 / HEAD 要不要移动
  2. 暂存区要不要跟着目标提交重置
  3. 工作区文件要不要也被覆盖

这三问基本就对应了 soft、mixed、hard 的差别。

最常见的三类用途

1. 撤回提交但保留改动

git reset --soft HEAD~1

2. 取消暂存

git reset HEAD path/to/file

3. 彻底回退到某个安全点

git reset --hard <commit>

一个更稳的操作顺序

当你准备做可能破坏当前状态的 reset 时,推荐顺序是:

  1. git status
  2. git log --oneline --decorate -5
  3. git reflog
  4. 如有必要先建救援分支
  5. 再执行 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 前,先做至少一件事:

  1. git status
  2. git reflog
  3. 建一个救援分支

一个实战判断原则

如果你的目标是:

  • 重新整理本地未共享提交:可以考虑 reset
  • 撤销已经共享给团队的历史:优先考虑 revert
  • 只想恢复文件内容:优先考虑 restore

这条命令在流程里解决什么问题

git reset 直接影响历史表达、引用位置或提交之间的关系。读这类命令时,要先判断这次操作是在整理本地未共享历史,还是在处理已经公开给团队的历史。

典型用例

  • 在合并、回滚、挑提交或整理提交序列时,用 git reset 重塑历史表达。
  • git reset 放进“先备份、再变更、最后复核”的高风险操作流程,降低误操作损失。
  • 在复盘冲突、回滚事故或判断分支关系时,用 git reset 理清提交之间的因果链。

图例理解

历史命令的作用面历史类命令通常围绕提交、当前分支和祖先关系展开,差别在于它是新增历史、移动引用,还是重写已有序列。
输入
提交序列当前分支祖先关系
结果
新的提交关系移动后的引用可恢复路径
这类命令执行前最值得确认的一件事,是“这段历史是不是已经共享给别人”。

特殊情况与边界

  • 历史类命令最常见的风险,是对已经共享出去的提交继续做重写或移动。
  • 如果这次操作可能影响团队协作,先跑 git statusgit log --oneline --graphgit reflog,再决定是否继续。
  • 一旦不确定,就先建一个备份分支,让自己保留“能回去”的选项。
  • 只要涉及 --hard,就应该先确认工作区里有没有还没备份的重要改动。

跟着做一遍

练习:比较 reset 三种模式

这一组练习最重要的是观察 HEAD、暂存区和工作区分别发生了什么,而不是只记住参数名字。

准备环境
git switch -c lab/reset-demo
# 连续做两次提交
# 再额外修改一个文件并执行 git add
跟着做
  1. 先运行 `git reset --soft HEAD~1` 并观察 `git status`。
  2. 再重复实验,改用 `git reset --mixed HEAD~1`。
  3. 最后只在实验仓库中试一次 `git reset --hard HEAD~1`。
结果会怎样
  • `--soft` 会保留暂存区和工作区内容。
  • `--mixed` 会把暂存内容退回工作区。
  • `--hard` 会让 HEAD、暂存区和工作区一起回到目标提交。
常见错误判断
  • 如果你真正想要的是撤回提交但保留改动,通常不该直接选 `--hard`。
  • 如果旧提交已经共享给团队,应该优先评估 `revert`,而不是直接 reset 共享历史。
  • 只要你不确定恢复路径,先跑 `git reflog` 再继续。

继续学习建议

接下来建议继续补:

  1. git reflog
  2. git restore
  3. git revert