Best Practices

共享历史的改写边界

明确哪些历史可以放心整理,哪些历史应该默认视为共享并谨慎处理,避免 rebase、amend、reset 和 force push 伤到别人。

这件事为什么比“会不会 rebase”更重要

真正危险的从来不是某一条命令,而是你在错误的历史边界上使用了它。commit --amendrebase -ireset --soft 本身都很有用,但一旦这段历史已经被别人拉走并继续开发,风险就完全变了。

1. 一个最实用的判断规则

可以先把历史粗略分成三类:

  • 只在自己本地:可以大胆整理
  • 已推送但无人依赖:谨慎整理
  • 已共享并可能被别人基于它继续开发:默认不要改写

如果你根本不确定属于哪一类,最稳的办法就是先按“已共享历史”处理。

2. 哪些命令会改写历史表达

以下命令都会改变别人理解你这段历史的方式:

  • git commit --amend
  • git rebase -i
  • git reset
  • git push --force

它们不是“坏命令”,但都要求你先知道自己站在哪条边界上。

3. 个人分支为什么适合整理

在个人分支上做这些动作通常很合理:

  • 合并碎片提交
  • 调整提交顺序
  • 把修正补进上一提交
  • 删除不该出现的噪声提交

因为此时你影响的主要还是自己,整理收益通常大于成本。

4. 主分支和共享分支为什么要默认保守

一旦历史已经被共享,改写的代价就不只是“我本地需要处理一下”,而是:

  • 别人的分支基底可能失效
  • review 链接和讨论上下文可能混乱
  • 自动化流程和回滚定位会更难对应

这也是为什么官方书一直强调,不要 rebase 那些已经公开出去、别人可能依赖的提交。

5. 与其改写共享历史,不如增加新历史

共享历史里更安全的思路通常是:

  • git revert 新增一个撤销提交
  • 用新的修复提交继续向前
  • 用 merge 保留历史关系

也就是说,进入共享边界以后,默认应该更偏向“追加解释”,而不是“擦掉重来”。

6. force push 真正危险的地方

git push --force 的危险不只是覆盖远端,而是它会让别人本地对那段历史的理解瞬间失效。

如果确实非推不可,至少应该满足两个条件:

  1. 这是一段尚未广泛共享的历史
  2. 团队已经明确知道你要改写它

并且优先改用:

git push --force-with-lease

因为它会先确认远端引用是否还停留在你预期的位置。

7. 一个很实用的团队边界共识

可以把规则简化成下面四句:

  1. 本地历史可以整理
  2. 已推送历史默认谨慎
  3. 共享主线默认不改写
  4. 不确定时按共享历史处理

这比试图让每个人都记住所有危险命令更有效。