必须用 git revert 回滚已推送的提交,因其生成逆操作新提交而不改历史;git reset --hard 仅适用于未共享的本地提交,否则会破坏协作。

别用 git reset --hard 去回滚别人已经拉过的提交——这是最常踩的坑,也是唯一必须先说清楚的事。
git revert 会生成新提交,不改历史
它本质是“反向打补丁”:对目标 commit 的所有变更做一次逆操作,再提交为一个新的 commit。所以原提交还在,只是被抵消了。
- 适合已推送到远程、多人协作的分支(如
main或develop) - 执行后
git log里能看到两个相邻的提交:一个是原错误提交,一个是revert提交 - 后续如果要合并老分支,不会重复引入已被
revert的修改(因为 Git 能识别“这个变更已被撤销过”) - 命令示例:
git revert abc1234(撤销单个提交),git revert abc1234..def5678(撤销一段范围,注意是左开右闭)
git reset 会移动 HEAD,直接删掉提交记录
它不是撤销,而是把分支指针往回拽,让后面的提交“不可达”。默认是 --mixed 模式,但真正危险的是 --hard。
-
git reset --soft abc1234:只动 HEAD,暂存区保留,适合重新打包提交 -
git reset --mixed abc1234(默认):HEAD 和暂存区重置,工作区文件不变,适合撤回 add 后还没 commit 的内容 -
git reset --hard abc1234:HEAD、暂存区、工作区全清空,所有未推送的后续修改彻底丢失 - 一旦
push过去,再reset --hard就必须git push --force,这会强制覆盖远程历史,其他协作者pull时会出错
选哪个?看提交是否已共享
核心判断只有一条:那个出问题的 commit,有没有被别人 fetch 或 pull 过?
- 没推过、或只在自己本地分支:用
git reset --hard最快,干净利落 - 已
push到远程、且别人可能基于它开发:必须用git revert,否则会破坏协作基础 - 想删掉最近几次提交但保留修改内容:用
git reset --soft HEAD~2,然后git commit合并成一个 - 误删了工作区文件但还没
add:别用 reset,用git checkout HEAD -- path/to/file(Git 2.23+ 推荐git restore)
容易被忽略的细节
git revert 不是万能的:如果目标 commit 后面有大量冲突性修改,revert 可能失败,需要手动解决;而 git reset --hard 看似简单,但它删掉的不只是提交——比如你刚 git add 了某个配置文件但没 commit,reset --hard 会连这个暂存状态一起清掉,且无法通过 reflog 恢复(除非你记得查 git reflog 并用 git reset --hard HEAD@{1} 回捞)。


















