Best Practices
共享历史的改写边界
明确哪些历史可以放心整理,哪些历史应该默认视为共享并谨慎处理,避免 rebase、amend、reset 和 force push 伤到别人。
这件事为什么比“会不会 rebase”更重要
真正危险的从来不是某一条命令,而是你在错误的历史边界上使用了它。commit --amend、rebase -i、reset --soft 本身都很有用,但一旦这段历史已经被别人拉走并继续开发,风险就完全变了。
1. 一个最实用的判断规则
可以先把历史粗略分成三类:
- 只在自己本地:可以大胆整理
- 已推送但无人依赖:谨慎整理
- 已共享并可能被别人基于它继续开发:默认不要改写
如果你根本不确定属于哪一类,最稳的办法就是先按“已共享历史”处理。
2. 哪些命令会改写历史表达
以下命令都会改变别人理解你这段历史的方式:
git commit --amendgit rebase -igit resetgit push --force
它们不是“坏命令”,但都要求你先知道自己站在哪条边界上。
3. 个人分支为什么适合整理
在个人分支上做这些动作通常很合理:
- 合并碎片提交
- 调整提交顺序
- 把修正补进上一提交
- 删除不该出现的噪声提交
因为此时你影响的主要还是自己,整理收益通常大于成本。
4. 主分支和共享分支为什么要默认保守
一旦历史已经被共享,改写的代价就不只是“我本地需要处理一下”,而是:
- 别人的分支基底可能失效
- review 链接和讨论上下文可能混乱
- 自动化流程和回滚定位会更难对应
这也是为什么官方书一直强调,不要 rebase 那些已经公开出去、别人可能依赖的提交。
5. 与其改写共享历史,不如增加新历史
共享历史里更安全的思路通常是:
- 用
git revert新增一个撤销提交 - 用新的修复提交继续向前
- 用 merge 保留历史关系
也就是说,进入共享边界以后,默认应该更偏向“追加解释”,而不是“擦掉重来”。
6. force push 真正危险的地方
git push --force 的危险不只是覆盖远端,而是它会让别人本地对那段历史的理解瞬间失效。
如果确实非推不可,至少应该满足两个条件:
- 这是一段尚未广泛共享的历史
- 团队已经明确知道你要改写它
并且优先改用:
git push --force-with-lease
因为它会先确认远端引用是否还停留在你预期的位置。
7. 一个很实用的团队边界共识
可以把规则简化成下面四句:
- 本地历史可以整理
- 已推送历史默认谨慎
- 共享主线默认不改写
- 不确定时按共享历史处理
这比试图让每个人都记住所有危险命令更有效。