Vibe Tutorial
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. 本章小结

  1. 未 Push 用 Reset:烂在自己肚子里的事,可以当没发生过。
  2. 已 Push 用 Revert:大家面前犯的错,要公开改正。
  3. Soft 是爱:尽量用 reset --soft,它给你后悔的机会;--hard 是无情的杀手。