Git 版本控制与跨平台协作
10.6 回滚操作实战
Tip
世界上没有后悔药,但 Git 有。
1. 为什么要学这个?
代码上线后突然发现重大 Bug。 或者你手滑把没写完的代码也提交了。 这时候你需要时光倒流。 但 Git 有两种时光倒流的方式,选错一种,你可能会连累全队人陪你一起丢代码。
Reset (重置) 是毁灭证据,Revert (撤销) 是承认错误。在公共场合,请做一个诚实的人。
2. 核心概念:Reset vs Revert
1. Reset (重置) = "没发生过"
- 动作:强行把时光机指针拨回昨天。
- 后果:该时间点之后的所有未来(Commit)都会消失。
- 适用:这事只有天知地知你知(本地分支)。
2. Revert (撤销) = "负荆请罪"
- 动作:我不删除错误,我新增一个"反向操作"来抵消它。
- 后果:历史记录里会留下一笔:"Create Bug" -> "Revert Bug"。
- 适用:这事全村都知道了(公共分支)。
3. 解决方案 (HOW)
场景 A: 我刚 commit 了垃圾代码,还没 push (用 Reset)
# --soft: 撤销 commit 记录,但保留代码在暂存区 (最安全,推荐)
git reset --soft HEAD~1
# --hard: 彻底回到过去,连代码都不要了 (极度危险,慎用!)
git reset --hard HEAD~1
场景 B: 坏代码已经 push 到了 main 分支 (用 Revert)
# 1. 找到坏蛋 commit id (比如是 a1b2c3d)
git lg
# 2. 生成一个反向 commit
git revert a1b2c3d
# (Git 会自动提交一个新的 commit,内容是反向的)
# 3. 推送
git push
区别示意图
1. Git Reset (毁灭)
graph TD
A1["Commit A"] --> B1["Commit B"] --> C1["Commit C"]
C1 -.->|Reset to B| B1
C1_Gone["C 消失了"]
style C1_Gone fill:#eeeeee,stroke-dasharray: 5 5
style B1 fill:#ffcdd2,stroke:#c62828
2. Git Revert (抵消/安全)
graph TD
A2["Commit A"] --> B2["Commit B"] --> C2["Commit C"]
C2 --> D2["Commit D (Revert C)"]
D2 -.->|内容等于| B2
style D2 fill:#c8e6c9,stroke:#2e7d32
4. 真实案例
Story
实习生的"核按钮"重置事件
某互联网大厂的一个实习生,为了撤销自己在 main 分支上的一次错误提交,在本地执行了 git reset --hard 回到了昨天。
这还没完,因为本地落后于远程,他为了推上去,加了 -f (Force Push) 参数:git push -f origin main。
灾难发生了:
远程仓库的 main 分支被强行重置到了昨天。
团队里其他 10 个人在今天提交的所有代码,全部在远程消失了。
虽然 Git 有 Reflog 可以抢救(很难),但那天下午整个团队都停止了开发,专门用来修补历史。
Vibe 心法:git push -f 只有在一种情况下是合法的:那个分支只有你一个人在用。除此之外,任何对公共历史的篡改都是蓄意破坏。
5. 本章小结
- 未 Push 用 Reset:烂在自己肚子里的事,可以当没发生过。
- 已 Push 用 Revert:大家面前犯的错,要公开改正。
- Soft 是爱:尽量用
reset --soft,它给你后悔的机会;--hard是无情的杀手。