Reset vs Revert
在 Git 中,reset 和 revert 都是用于撤销更改的命令,但它们的工作方式和适用场景有很大的不同。
核心区别
git reset:时间倒流。它通过移动 HEAD 指针到指定的提交,从而“抹去”之后的提交记录。这会修改历史。git revert:向前滚动。它创建一个新的提交,这个新提交的内容是用来抵消(撤销)指定提交的更改。这不修改历史,只是增加了新的历史。
1. Git Reset (重置)
git reset 主要用于本地未推送(push)的提交,或者你确定没有其他人基于你的分支进行开发的情况。
三种常用模式
| 模式 | 命令 | HEAD 指针 | 暂存区 (Index) | 工作区 (Working Dir) | 适用场景 |
|---|---|---|---|---|---|
| --soft | git reset --soft <commit> | 移动 | 保留更改 | 保留更改 | 撤销了提交,但保留了代码和 git add 状态。适合想重新提交(修改 commit message 或合并多个 commit)。 |
| --mixed (默认) | git reset <commit> | 移动 | 重置 (清空) | 保留更改 | 撤销了提交和 git add。适合想重新挑选文件进行提交。 |
| --hard | git reset --hard <commit> | 移动 | 重置 (清空) | 重置 (清空) | 彻底毁灭。撤销所有更改,回到指定 commit 的状态。慎用! |
示例图解
假设当前历史是:A -> B -> C (HEAD)
执行 git reset --hard B 后: 历史变为:A -> B (HEAD) Commit C 就像从未发生过一样(除非通过 reflog 找回)。
⚠️ 注意
千万不要对已经推送到公共仓库(Public Remote)的提交使用 git reset,这会导致其他协作者的历史混乱。
如果git reset后,版本回退的,无法直接push到远程仓库(因为远程仓库版本更新),git push -f覆盖推送即可,效果:远程仓库的版本也进行回退
2. Git Revert (回滚)
git revert 适用于公共分支或已经推送到远程仓库的提交。它是一种安全的撤销方式。
用法
bash
git revert <commit-hash>示例图解
假设当前历史是:A -> B -> C (HEAD)
执行 git revert C 后: 历史变为:A -> B -> C -> D (HEAD)
其中 Commit D 的内容与 Commit C 的修改完全相反(例如 C 增加了一行,D 就删除那一行)。
优势
- 安全:不会改变现有的项目历史。
- 可追溯:撤销操作本身也有记录,方便日后查阅。
总结
| 特性 | Git Reset | Git Revert |
|---|---|---|
| 历史记录 | 被修改(消失) | 被保留(新增撤销提交) |
| 适用范围 | 私有分支 / 本地未推送 | 公共分支 / 已推送代码 |
| 风险 | 较高(可能丢失代码或冲突) | 较低(只是增加新提交) |
| 思维模型 | "如果我能回到过去..." | "我做错了,我要修正它..." |