v3 提审冲刺 · Git 协作约定(强制)

适用:kailash 仓库全部工作树 / 全部分支 / 全体开发者(波波 / 小冈 / 小齐 / 冈子 / 阿仁)。
生效方式:见本文「七、全员如何生效」。本约定为强制,违反将被 pre-commit 或 pre-receive 拦截。

一、为什么现在要立这条

v3 进入提审前全力冲刺,多人(波波 / 小冈 / 小齐 / 冈子 / 阿仁)会在同一仓库并行工作。已发生两类事故,必须根治:

  1. 署名串味:本仓库是多工作树共享同一 .git,本地 user.name/user.email 是「谁最后提交就是谁」。实测:波波在共享 worktree 提交,本地 config 当时是小冈,波波的代码被署成小冈。
  2. 推送被拒:pre-receive 校验 author ↔ 推送账号,波波用 bobo 账号推送含小冈署名的分支 → 直接拒。

根因不是谁写错,是「依赖本地 config 的 user.*」在共享 worktree 下必然串味。


二、核心规则(强制)

  1. 每一次提交都必须显式声明 --author,与你的推送账号一致。 禁止依赖本地 config 的 user.*。
  2. 推送账号与 author email 必须匹配,否则 pre-receive 拦截。
  3. -c user.name=... 在本机不稳(中文名在工具 shell 引号里会被吞),一律用 git commit --author="姓名 <邮箱>"。

三、命令模板(直接抄)

# 普通提交(必带 --author)
git commit --author="波波 <bobo@kailash.media>" -m "feat: ..."

# 改最近一笔的署名(发现串味立即改回)
git commit --amend --author="波波 <bobo@kailash.media>" --no-edit

# 改最近 N 笔的署名(rebase 场景,慎用:--reset-author 会用当前 config 身份,可能再次串味)
# 优先逐笔 --author,或 rebase 后逐笔 amend
GIT_SEQUENCE_EDITOR=: git rebase <base> --exec 'git commit --amend --no-edit --reset-author'

四、账号映射(author email = 推送账号)

成员author推送通道
波波波波 <bobo@kailash.media>https://bobo@doc.kailashi.cn/git/kailash.git
小冈小冈 <xiaogang@kailash.media>xiaogang 通道(xiaogang@doc.kailashi.cn)
小齐小齐 <xiaoqi@kailash.media>xiaoqi 通道(历史也用过 @kailashi.cn / @kailashi.media)
冈子冈子 <gangzi@kailash.media>gangzi 通道
阿仁阿仁 <aren@kailash.media>aren 通道(历史也用过 @kailashi.cn)
提交前确认 --author 与你要用的推送 URL 账号一致。各人账号以实际为准,发现串味立即 --amend --author 修正。
小齐 / 阿仁 历史用过 @kailashi.cn,若 pre-receive 按 @kailash.media 校验,统一回 @kailash.media 提交。

五、推送前自查(每次 push 前必跑)

git log --format='%h %an <%ae> %s' -3

author 必须是本人;若发现串味,先 amend 改回再推。


六、pre-commit 钩子自动拦截

仓库已内置 .githooks/pre-commit:提交时自动校验,否则本地直接拦截(在 pre-receive 之前就拦住,省得推了才报错)。

钩子校验两条规则(2026-09-28 冈子补强第二条):

  1. 邮箱域校验(波波 09-28 原版):author email 必须 @kailash.media 域。
  2. 名↔邮箱配对校验(冈子 补强):邮箱前缀必须等于代号拼音,且名字必须是该代号对应的中文名。

例:冈子 <gangzi@kailash.media> 通过 / 波波 <gangzi@kailash.media> 被拒。

为什么补第二条:原版只查邮箱域,波波 <gangzi@kailash.media> 会被本地放行,
但服务端 pre-receive 比对的是 author 名(%an),必然拒收 ⇒ 白跑一次 push 往返。
补强后本地即拦住同类错误。

校验粒度对照(2026-09-28 读服务端钩子源码核实):

校验点本地 pre-commit服务端 pre-receive
邮箱域必须 @kailash.media不校验(仅报错时打印)
名↔邮箱配对校验不校验(只看名字)
名字 ↔ 账号不校验(本地无账号概念)校验(比对 %an)
覆盖分支全部(本地提交即触发)全部(无 main 白名单)
结论:本地比服务端严。两条都过 ⇒ 服务端必过。以本文件为准执行。

钩子校验逻辑:读取 git var GIT_AUTHOR_IDENT → 提取名字与邮箱 → 逐条比对 → 任一不符即退出 1。

若你忘记写 --author,钩子会提示正确写法,不会放行。

七、全员如何生效

本约定与钩子推在分支 bobo/v3-git-conventions。所有人执行一次即可永久生效:

# 1. 取到本约定分支(含文档 + 钩子)
git fetch origin bobo/v3-git-conventions

# 2. 读约定
git show origin/bobo/v3-git-conventions:docs/v3-git-conventions.md

# 3. 启用钩子(共享 .git 的仓库设一次即对全部工作树生效)
git config core.hooksPath .githooks
设 core.hooksPath 后,本仓库所有提交都会过 author 校验;谁漏写 --author 谁当场被拦。

八、后续待固化的约定项(提审后随分工补完)

以下纪律 v3 冲刺期已口头执行,待分工明确后写入本文件:

  1. 分支基于最新 main、勤 rebase:禁止长期落后 main 再合并(本次波波分支落后 87 提交,合 main 炸出 16 个全局样式冲突)。每人分支每周 rebase 到 origin/main。
  2. 锁域纪律:selection / profile / local 属小冈 WIP-275 锁域;跨域改他人锁域文件须刘总令。
  3. 解冲突保留 main 修复:合并冲突时,main 的既有修复(如 status-timeline 空白文字、merchant→主理人)不得被覆盖丢失。
  4. 每人独立 worktree + 独立分支(根治项):从根上消除共享 config 串味。当前阶段先靠本约定守。

九、根治方向

每人独立 worktree + 独立分支,本地 user.* 各自设好,从根上消除共享 config 串味。当前阶段(v3 提审前、尚未分工)先靠本约定 + pre-commit 钩子守。