git reset 的 soft、mixed、hard 三种模式怎么选
git reset 三种模式:--soft 只移动引用(保留原暂存区和工作区),--mixed(默认)同时重置暂存区(改动留在工作区),--hard 重置索引及跟踪文件,可能删除阻挡写入的未跟踪路径。撤销提交用 soft/mixed,丢弃代码才用 --hard。
三种模式的区别就在于"撤销提交后,改动去哪":--soft 只移动引用,保持暂存区和工作区不变;--mixed(默认)改动回到工作区;--hard 重置索引和跟踪文件,丢弃相应未提交改动,并可能删除阻挡写入的未跟踪路径;不是删除所有未跟踪文件。记忆口诀:soft 最温柔只动指针,hard 最粗暴全丢,mixed 居中。
下面按当前分支有父提交、工作区和暂存区原本干净的情形说明;已有暂存/未暂存改动时,soft 不会自动只留下最后一个提交的补丁。根提交没有 HEAD~1,游离 HEAD 和带路径的 reset 也有不同作用域。
图解
提交历史: A---B---C(HEAD)
工作区/暂存区: 与 C 快照一致、无未提交改动
git reset --soft HEAD~1 → 分支指向 B,C 的改动在暂存区(git commit 直接重提)
git reset --mixed HEAD~1 → 分支指向 B,C 的改动在工作区(未暂存)
git reset --hard HEAD~1 → 分支指向 B,改动彻底消失
各模式的典型场景
# --soft:刚提交就想重做这个提交(换信息/增删文件)
git reset --soft HEAD~1 && git commit -m "更好的信息"
# --mixed:想把已提交的内容拆成多个小提交
git reset HEAD~1 && git add -p && git commit ...
# --hard:这堆改动彻底不要了
git reset --hard HEAD~1
hard 的安全网
--hard 丢弃的提交和改动看似没了,但提交对象仍在:git reflog 找到哈希,先 git branch recovery <哈希> 保存恢复引用,再选择恢复方式,避免立即覆盖现有工作区(前提是提交对象仍存在)。未提交过的工作区改动则真的找不回——hard 前想清楚。
常见问题(FAQ)
Q:git reset 不带参数干什么?
git reset(等价 mixed HEAD):把暂存区重置到 HEAD——就是"取消所有 git add",工作区改动保留。
Q:reset 到某个历史提交而不是 HEAD~N?
git reset --hard a1b2c3d 直接回到任意提交。配合 git log --oneline 先找目标。
Q:reset 和 revert 怎么选?
本地未推送的历史用 reset 改写;已推送、共享的历史用 revert(新增反向提交)——reset 改写公开历史会坑队友。