文章

git reset 完整详解

git reset 的三种模式、适用场景、注意事项与常见误区

git reset 完整详解

git reset 完整详解

1
git reset [--soft | --mixed | --hard] 目标提交

HEAD:当前分支最新提交
索引区(stage):暂存区
工作区:本地磁盘中的文件内容

先看结论:三种模式的区别

模式影响范围提交是否删除暂存区工作区适用场景
--soft仅移动 HEAD是保留保留修改提交信息 / 重写提交
--mixed移动 HEAD + 清空暂存区是清空保留重新挑选文件再提交
--hard彻底回退是清空清空彻底放弃最近改动

1. --soft 软重置 ⭐ 最轻

移动 HEAD,删除提交;暂存区和工作区中的文件都保持不动

1
git reset --soft HEAD~1
  • 撤销最近 1 次 commit,代码还停留在暂存区,可以直接继续修改后重新提交
  • .git 体积不会立刻变小,因为旧提交对象还在 Git 对象数据库中
  • 只是在“提交历史”上回退了一步,改动还在本地等待重新提交

适用:写错 commit 信息、想重新提交前再整理内容。


2. --mixed(默认行为,不加参数就是它)

移动 HEAD,删除 commit;清空暂存区;工作区保持不变

1
2
3
# 两条命令等价
git reset HEAD~1
git reset --mixed HEAD~1
  • 提交被撤销了,但文件内容还保留在工作目录中
  • 之前 git add 的内容会从暂存区退回,需要重新执行 git add
  • 这是最常见、最实用的回退方式

适用:撤销提交后,想重新挑选哪些文件进入下一次提交。


3. --hard 硬重置 ⚠️ 危险

移动 HEAD;提交、暂存区、本地未提交修改全部清空,代码直接丢失

1
git reset --hard HEAD~1

⚠️ 这会直接抹掉所有未提交修改,除非你提前做了 stash 或者能从 reflog 中找回。
对于单人开发,可能是快速“回到过去”的方式;但在多人协作时,切记不要滥用。

适用:彻底抛弃最近几次提交,不再保留这些改动。


reset 之后,.git 文件夹不会立刻变小

很多人执行完 git reset --hard 后,会发现 .git 的占用空间并没有马上减少。

原因:Git 还没有真正回收旧提交对象,而是先把它们留在 reflog 中,等待垃圾回收。

如果你确认历史已经不需要,可以手动清理:

1
2
git reflog expire --expire=now --all
git gc --prune=now --aggressive

这一步会强制清理已经失效的对象,让 .git 体积真正缩小。


远程仓库怎么办

1
2
# 强制推送覆盖远程(多人协作仓库禁止!!)
git push -f origin main

多人项目里,优先考虑 git revert,不要轻易使用 reset --hard 去覆盖别人已经推送的提交。

如果你只是想“回退一个已提交的错误版本”,通常更稳妥的方式是:

1
git revert HEAD

这样不会直接改写历史,而是新增一个反向提交,团队协作时更安全。


一张图理解三种模式

1
2
3
4
5
6
7
HEAD
  ↓
  提交记录

--soft  : 只移动 HEAD,改动停留在暂存区
--mixed : 移动 HEAD,并清空暂存区,改动回到工作区
--hard  : 移动 HEAD,并抹掉暂存区与工作区中的改动

最后总结

  • --soft:最安全,适合继续完善提交
  • --mixed:最常用,适合重做提交内容
  • --hard:最危险,适合彻底放弃修改

如果你是在写作业、修复 Bug,或者重写提交时,最推荐先用 --mixed、再根据需要决定是否 --soft/--hard。

本文由作者按照 CC BY 4.0 进行授权