🛠️ 第13章 从个人开发助手到团队级研发流程
📄 一句话概括

三层配置:默认层(能力包自带)、团队层(进仓库走 review)、个人层(不进仓库)。 个人层改「偏好」可以,改「权限」要拦——比如把自动提交从关改成开。 能力包一旦被两个项目用,就必须版本化:让升级变成可选项。

📝 本章和前面几章的关系

上一篇讲了什么时候该共享。这一篇讲共享什么、怎么合。 为什么不能大家都用同一份配置? 因为「约定」和「偏好」是两种东西。 行宽多少是约定,要不要自动提交是权限——混在一份文件里,改行宽的人会顺手把权限也改了。 Demo 拿三份配置真合并一遍:默认六个键、团队覆盖三个、个人又覆盖两个。 再对比三个项目在能力包升级时的损坏数:锁版本零处,不锁两处。

一、规则怎么共享

三层,各管一段。

层 放哪 谁能改 盖谁
默认层 能力包自带 维护者 —
团队层 仓库里的配置文件 团队,走 review 默认层
个人层 本地文件,不进仓库 本人 团队层

三层的关键是「个人层不进仓库」这条。 它让人可以为自己调,但调的东西不会污染别人。 如果没有这一层,会发生两件事: 一是所有人都在改团队文件,改完就冲突; 二是有人干脆不改,忍着用不合适的配置,然后慢慢不用了。 合并顺序是「默认 → 团队 → 个人」,后盖前。 Demo 里团队盖了三个键、个人又盖了两个,六个键里五个被改过—— 这很正常。团队化的目的不是「所有人一样」,是「不一样的地方有个说法」。 所以合并的时候要留一条痕迹:谁盖了谁、盖成了什么。 这条痕迹不拦人,它的作用是「出问题的时候能查」。

二、权限怎么分

有一类配置不该跟偏好混在一起。

配置 性质 能不能个人改
行宽、缩进 偏好 能
测试命令 约定 能,但要跟团队说
自动提交、跳过检查 权限 不能
凭据、密钥 秘密 不进配置

第三行是这一节的落点。 「自动提交」听起来是个效率开关,但它实际改变的是「没人看过就进主干」这件事的边界。 这种开关放在个人层,等于每个人自己决定要不要审批。 Demo 里那句话说得直白:那属于权限,不属于偏好。 判据是「这个开关会不会让某道闸门失效」——会让闸门失效的,一律不许个人改。 第四行也值得注意:凭据不进配置。 它应该进环境变量或者密钥管理,而不是一份会被 commit 的文件。 这一条在很多团队是「知道但没做」,直到某次提交里出现一串 sk- 开头的东西。

三、能力包怎么版本化

Demo 里三个项目:服务 A 锁 v1、服务 B 锁 v2、服务 C 不锁。 能力包从 v1 升到 v2 时改了两处签名,结果 A 和 B 一处都没坏,C 坏了两处。 这个对比说明版本化的真正作用:让「升级」从「必然发生」变成「可以选择」。 不锁版本,升级是被动的——别人发了新版,你下次安装就跟着变。 版本化要做得有用,得满足两条。 第一条:旧版本还能用——如果 v1 发布后就被删了,锁版本是空话。 第二条:变更要说清是「破坏性」还是「兼容」——这跟 11.2 讲接口契约的判定是同一套标准。 为什么「被两个以上项目用」是版本化的触发条件? 因为一个项目用的时候,改坏了当场就知道;两个项目用的时候,改坏了是「另一个项目下周构建挂了」。 时间差就是成本。

四、共享什么、不共享什么

共享 不共享
规则文件 个人的快捷键和别名
能力包(带版本) 本地路径与绝对目录
CI 的检查项 个人的登录凭据

右边三样有一个共同点:换个人就跑不通。 换个人跑不通的东西一旦共享,第一个受害的是新同事。 「本地路径」这一条特别常见。 有人把 /Users/zhang/work/... 写进了共享配置,自己跑得好好的,别人一跑就报「文件不存在」。 这种错查起来很费劲,因为报错说的是「文件不存在」,没人会想到是配置里写死了别人的路径。 所以共享的判据可以写得很硬:把这份配置给一个新人,他能不能直接跑通。 能,就可以共享;不能,就说明里面还有属于你的东西。

五、动手 Demo:共享规则、权限与能力包:三层配置怎么合

三份配置:默认六个键、团队覆盖三个、个人又覆盖两个。真合并一遍。 再对比三个项目在能力包升级时的损坏数:锁版本和不锁版本。 合并是按「后盖前」做的,冲突是逐键比出来的——三张表里的每个值都是脚本算的,不是我填的。

DEFAULT_CFG = {"format.line_width": "98", "agent.max_files": "10",
               "agent.auto_commit": "false", ...}
TEAM_CFG = {"format.line_width": "100", "agent.max_files": "6", ...}
LOCAL_CFG = {"format.indent": "2", "agent.auto_commit": "true"}

merged = dict(DEFAULT_CFG)
merged.update(TEAM_CFG)
merged.update(LOCAL_CFG)

for k in sorted(DEFAULT_CFG):
    print(k, DEFAULT_CFG[k], TEAM_CFG.get(k, "—"),
          LOCAL_CFG.get(k, "—"), merged[k])

实跑输出:

--------------------------------------------------------------------
共享规则、权限与能力包:三层配置怎么合
--------------------------------------------------------------------

  团队化的核心不是「大家用同一个工具」,是「大家对同一套约束有一致的理解」。

  ① 三层配置,谁盖谁
  --------------------------------------------------------------------
| 层 | 放哪 | 谁能改 | 盖谁 |
|---|---|---|---|
| 默认层 | 能力包自带 | 维护者 | — |
| 团队层 | 仓库里的配置文件 | 团队,走 review | 默认层 |
| 个人层 | 本地文件,不进仓库 | 本人 | 团队层 |

  三层的关键是「个人层不进仓库」。它让人可以为自己调,但调的东西不会污染别人。

  ② 真合并一遍
  --------------------------------------------------------------------
| 键 | 默认 | 团队 | 个人 | 结果 |
|---|---|---|---|---|
| agent.auto_commit | false | — | true | true |
| agent.max_files | 10 | 6 | — | 6 |
| format.indent | 4 | — | 2 | 2 |
| format.line_width | 98 | 100 | — | 100 |
| linter.enabled | true | — | — | true |
| test.command | unittest discover | unittest -s tests | — | unittest -s tests |

  团队层覆盖了 3 个键,个人层又覆盖了 2 个。

  ③ 合并要报冲突,不能默默盖
  --------------------------------------------------------------------
| 键 | 被盖的值 | 盖上去的值 | 性质 |
|---|---|---|---|
| agent.max_files | 10 | 6 | 团队盖默认 |
| format.line_width | 98 | 100 | 团队盖默认 |
| test.command | unittest discover | unittest -s tests | 团队盖默认 |

  3 条里 3 条是「团队盖默认」——那是正常的。
  标注出来的意义是「留下一条能查的痕迹」,不是「拦下来」。
  ! 真正该拦的只有一种:个人层把「安全相关」的键改宽了。
  比如把 agent.auto_commit 从 false 改成 true——那属于权限,不属于偏好。

  ④ 能力包版本化
  --------------------------------------------------------------------
| 项目 | 用的版本 | 锁没锁 | 升级后坏几处 |
|---|---|---|---|
| 服务 A | v1 | 锁 v1 | 0 |
| 服务 B | v2 | 锁 v2 | 0 |
| 服务 C | v1 | 不锁 | 2 |

  锁了版本的两个项目,升级到 v2 时一处都不坏;不锁的那个坏 2 处。
  ! 能力包一旦被两个以上项目用,就必须版本化。版本化不是「好看」,是「让升级这件事变成可选的」。

  ⑤ 共享什么、不共享什么
  --------------------------------------------------------------------
| 共享 | 不共享 |
|---|---|
| 规则文件 | 个人的快捷键和别名 |
| 能力包(带版本) | 本地路径与绝对目录 |
| CI 的检查项 | 个人的登录凭据 |

  右边三样有一个共同点:它们换个人就跑不通。换个人跑不通的东西一旦共享,第一个受害的是新同事。

合并表五行要看最后一列。 它跟前面三列一比,你就知道每个值是谁定的—— line_width 是团队定的,indent 是个人定的,linter 谁都没动。 冲突那三行全是「团队盖默认」,这是正常的。 真正要拦的是另一种:个人层把 auto_commit 从 false 改成 true。 它在合并表里显示成「个人盖团队」,性质却完全不同——前者是偏好,后者是权限。 能力包那张表三行,只有第三行坏了。 「不锁」这一行看起来最省事,实际上把「什么时候升级」的决定权交给了别人。 最后那张「共享 / 不共享」的表,右边三行的共同点是「换个人跑不通」。 这个判据比「重不重要」好用—— 因为「重要」是主观的,而「换个人能不能跑」一试就知道。

30 秒实验

  1. 翻你们的共享配置,找出三个绝对路径。 每一个都是一颗留给新同事的雷。
  2. 数一下你们有几个项目在用同一份能力包。 超过两个而没版本号的,现在加上。
  3. 检查一下你们的配置里有没有「跳过检查」「自动合并」这类键。 有的话,把它从个人层挪到团队层。

常见误区

  1. 「所有人用同一份配置最省事。」 省的是维护,贵的是适配。 没有个人层,人要么改团队文件,要么忍着不用。
  2. 「能力包不用版本号,反正只有一个版本。」 现在是,下个月就不是了。 等第二个项目接入再补版本号,已经有一次坏构建了。
  3. 「配置里写死路径方便调试。」 你调试方便,别人一跑就报「文件不存在」。 这种错查起来最费劲,因为报错完全不提配置。
自测三问(点开对答案) 1. 三层配置里哪一层不进仓库?为什么? —— **个人层。** **它让人可以为自己调,而调的东西不会污染别人。** 2. 哪种配置个人不能改?判据是什么? —— **会让某道闸门失效的那种,比如自动提交、跳过检查。** **那不是偏好,是权限。** 3. 能力包版本化的真正作用是什么? —— **让「升级」从必然发生变成可以选择。** **不锁版本,升级是被动的。**

下一篇讲多人同时改一个仓库:worktree 解决什么,以及异步协作靠什么交接。

相关笔记