Best Practices

共享历史的改写边界

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

适合谁看
  • 希望把 Git 用得更稳的个人或团队
  • 准备建立协作规范的维护者
前置知识
  • 至少有一次真实协作经验
  • 知道常见命令但还没形成稳定习惯
常见风险
  • 把建议当硬规则而忽略上下文
  • 只记流程,不理解背后的协作边界

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

共享历史边界一旦提交被推送到共享远端,它就成为团队共同的历史。不应该 rewrite 这部分历史。本地整理可以在推送前进行。
本地历史 (可安全 rewrite)
ABCD
推送边界: main
已推送历史 (不应 rewrite)
ABCM
BEF
团队共享历史 (禁止 force push)
ABCE'F'
推送边界: feature

很多人学 Git 时最关心的是

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. 不确定时按共享历史处理

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