<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[签入代码治理要求（Commit&#x2F;MR&#x2F;分支的可追溯治理）]]></title><description><![CDATA[<h1>签入代码治理要求（Commit/MR/分支的可追溯治理）</h1>
<h2>目标</h2>
<p dir="auto">把工程治理的最小闭环“工程化”：</p>
<ul>
<li>任何进入主干/可发布链路的变更，都必须可追溯到一个<strong>全局可索引主键（Key）</strong>。</li>
<li>追溯链路稳定：<code>Key -&gt; 分支 -&gt; Commit -&gt; MR -&gt; 代码变更</code>。</li>
<li>通过 CI 把规范“卡死”，避免靠自觉。</li>
</ul>
<h2>术语</h2>
<ul>
<li><strong>Key（工程主键）</strong>：全局唯一、可搜索、可聚合的变更主键。</li>
<li><strong>Intake Layer（需求接入层）</strong>：运营/需求方只接触的单一入口项目，不触碰 250 个仓库。</li>
</ul>
<h2>一、统一工程主键：Key 必须全局唯一（MUST）</h2>
<h3>1. Key 规则</h3>
<p dir="auto">Key 必须带<strong>来源前缀</strong>，保证全局唯一，避免同号冲突。</p>
<ul>
<li>禅道：<code>ZD-&lt;id&gt;</code>（例：<code>ZD-10452</code>）</li>
<li>Taiga：<code>TG-&lt;id&gt;</code>（例：<code>TG-8931</code>）</li>
<li>GitLab Intake Issue（推荐）：<code>REQ-&lt;iid&gt;</code>（例：<code>REQ-1234</code>）</li>
</ul>
<blockquote>
<p dir="auto">备注：未来新增系统，只需要新增前缀（例如 <code>JIRA-</code>、<code>WX-</code>），不破坏既有规则。</p>
</blockquote>
<h3>2. 禁止使用的写法（禁止）</h3>
<p dir="auto">以下写法会导致“搜索不稳定”，禁止：</p>
<ul>
<li><code>1234</code></li>
<li><code>#1234</code></li>
<li><code>bug1234</code></li>
<li><code>TAIGA-1234</code>（除非这是你们统一前缀）</li>
</ul>
<h2>二、三处强约束：分支名 + Commit + MR 都必须携带 Key（MUST）</h2>
<blockquote>
<p dir="auto">只强制一处会漏；三处都强制，GitLab 搜索必然命中。</p>
</blockquote>
<h3>1. 分支命名规范（MUST）</h3>
<p dir="auto">必须包含 Key，且 Key 紧跟类型后。</p>
<ul>
<li><code>feature/&lt;KEY&gt;-&lt;slug&gt;</code></li>
<li><code>bugfix/&lt;KEY&gt;-&lt;slug&gt;</code></li>
<li><code>hotfix/&lt;KEY&gt;-&lt;slug&gt;</code></li>
</ul>
<p dir="auto">示例：</p>
<ul>
<li><code>feature/ZD-10452-order-discount</code></li>
<li><code>bugfix/TG-8931-fix-null-ref</code></li>
<li><code>hotfix/REQ-1234-fix-payment-timeout</code></li>
</ul>
<h3>2. Commit message 规范（MUST）</h3>
<p dir="auto">Commit 第一行必须以 Key 开头：</p>
<ul>
<li><code>&lt;KEY&gt;: &lt;message&gt;</code></li>
</ul>
<p dir="auto">示例：</p>
<ul>
<li><code>ZD-10452: Fix discount rounding</code></li>
<li><code>TG-8931: Add validation for phone</code></li>
</ul>
<blockquote>
<p dir="auto">建议：合并提交（merge commit）也要包含 Key（如果你们允许 merge commit）。</p>
</blockquote>
<h3>3. MR 标题规范（MUST）</h3>
<p dir="auto">MR 标题必须包含 Key（建议放最前）：</p>
<ul>
<li><code>&lt;KEY&gt; - &lt;title&gt;</code></li>
</ul>
<p dir="auto">示例：</p>
<ul>
<li><code>ZD-10452 - Fix discount rounding</code></li>
<li><code>REQ-1234 - Payment timeout hotfix</code></li>
</ul>
<h2>三、用 CI 把规范卡死：没有 Key 不准合并（MUST）</h2>
<p dir="auto">靠制度和自觉会被绕开；CI 是唯一稳定控制点。</p>
<h3>必须校验的 3 条</h3>
<ol>
<li><strong>分支名</strong>必须包含合法 Key（<code>ZD-\d+|TG-\d+|REQ-\d+</code>）</li>
<li><strong>MR 标题</strong>必须包含合法 Key</li>
<li>**Commit messages（最近 N 个）**必须包含 Key（至少一个 Key；更严格可要求与分支 Key 一致）</li>
</ol>
<h3>建议策略</h3>
<ul>
<li>MR pipeline / merge request event 时执行（最有效）</li>
<li>主干 pipeline 也可再执行一次（兜底）</li>
</ul>
<h2>四、需求入口治理：运营不碰 250 个仓库（SHOULD）</h2>
<h3>结论</h3>
<ul>
<li>运营/需求方只接触<strong>一个 GitLab 项目</strong>（Intake Layer）</li>
<li>工程师才接触各个业务仓库</li>
</ul>
<h3>推荐组织结构</h3>
<pre><code>Group: company
|
|-- Group: _intake
|   |-- Project: requirements   (运营只在这里提 Issue)
|
|-- Group: products
|   |-- Project: erp1.0-sales
|   |-- Project: store-manage
|   |-- ... (工程仓库)
</code></pre>
<h3>Intake Issue 如何成为 Key</h3>
<ul>
<li>运营提 Issue 后，系统自动生成 IID</li>
<li>约定 Key 为：<code>REQ-&lt;iid&gt;</code></li>
<li>工程师在分支/commit/MR 中引用 <code>REQ-&lt;iid&gt;</code></li>
</ul>
<h2>五、合并策略：让“后门”消失（MUST）</h2>
<h3>合并到主干的硬规则</h3>
<ul>
<li>任何进入 <code>master/main</code> 的变更必须：
<ul>
<li>有 Key</li>
<li>走 MR</li>
<li>通过 CI 校验</li>
</ul>
</li>
</ul>
<h3>建议的最短制度句子（可写进团队规范）</h3>
<blockquote>
<p dir="auto">任何需要上线/进入主干的变更，必须有 Key（ZD/TG/REQ），否则拒绝合并。</p>
</blockquote>
<h2>六、落地清单（你可以逐项勾选）</h2>
<ul>
<li><div class="plugin-markdown"><input type="checkbox" />确认 Key 前缀集合（</div><code>ZD-</code>/<code>TG-</code>/<code>REQ-</code>）</li>
<li><div class="plugin-markdown"><input type="checkbox" />发布分支命名规范（feature/bugfix/hotfix）</div></li>
<li><div class="plugin-markdown"><input type="checkbox" />发布 Commit message 第一行规范（</div><code>&lt;KEY&gt;:</code>）</li>
<li><div class="plugin-markdown"><input type="checkbox" />发布 MR 标题规范（</div><code>&lt;KEY&gt; -</code>）</li>
<li><div class="plugin-markdown"><input type="checkbox" />在 CI 中增加校验 job（MR pipeline 必跑）</div></li>
<li><div class="plugin-markdown"><input type="checkbox" />建立 </div><code>_intake/requirements</code> 项目并统一入口</li>
</ul>
<h2>七、常见问题</h2>
<h3>Q1: 为什么 Key 要全局唯一？</h3>
<p dir="auto">因为你将来会做跨仓库聚合、审计、统计、回溯；如果 Key 不全局唯一（例如都叫 <code>1234</code>），必然出现误聚合。</p>
<h3>Q2: 为什么要三处都要带 Key？</h3>
<ul>
<li>分支：源头可见</li>
<li>commit：最终 diff 可追溯</li>
<li>MR：跨仓库聚合最稳定（你大概率以 MR 为中心）</li>
</ul>
<h3>Q3: 运营只面对一个入口，会不会增加工程团队负担？</h3>
<p dir="auto">短期会增加“路由/翻译”成本；但中长期会显著降低补账/救火成本，并让工程事实可审计，这是规模化治理唯一可行路径。</p>
]]></description><link>https://talk.loda.net/topic/38/签入代码治理要求-commit-mr-分支的可追溯治理</link><generator>RSS for Node</generator><lastBuildDate>Fri, 17 Apr 2026 08:18:57 GMT</lastBuildDate><atom:link href="https://talk.loda.net/topic/38.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 04 Jan 2026 00:40:28 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to 签入代码治理要求（Commit&#x2F;MR&#x2F;分支的可追溯治理） on Sun, 11 Jan 2026 00:57:43 GMT]]></title><description><![CDATA[<h2>1. 背景：我们为什么要改流程</h2>
<p dir="auto">近期我们在 CI/CD 与分支治理上做了一轮升级，目标很明确：</p>
<ul>
<li><strong>提升生产环境安全性</strong>：避免“谁改了 master 就把生产一起带崩”的风险</li>
<li><strong>提升可追溯性</strong>：每个改动都能对应到一个明确的需求/缺陷 Key（如 <code>ZD-xxx</code> / <code>TG-xxx</code> / <code>REQ-xxx</code>）</li>
<li><strong>在多仓库、多级触发（A-&gt;B-&gt;C）的情况下保持稳定</strong>：避免触发链路分支漂移、遗漏合并</li>
</ul>
<p dir="auto">这套升级会增加一些管理动作，但它换来的是<strong>可控、可审计、可回滚</strong>的发布链路。</p>
<hr />
<h2>2. 现场问题：为什么“我要上生产”会变成“要把所有人都合进去”</h2>
<p dir="auto">我们遇到的典型困惑是：</p>
<ul>
<li>当前大家都在 <code>develop</code> 上做修改</li>
<li>某个修复已经在 <code>develop</code> 测试通过，现在要发布生产</li>
<li>但 <code>develop</code> 同时包含其他人的改动<br />
一旦用 <code>develop -&gt; master</code> 合并，就会把<strong>其他人的改动也带上生产</strong><br />
结果看起来就像“流程绕了一圈，和以前直接改 master 没区别”，甚至更累</li>
</ul>
<p dir="auto">这不是某个人的问题，而是**“只有 master+develop 且大家直接改 develop”**这种工作方式的必然结果：<br />
<code>develop</code> 会自然变成“所有进行中的改动大杂烩”，<strong>不具备按需挑选发布的能力</strong>。</p>
<hr />
<h2>3. 根因剖析：为什么会出现“hotfix 从 develop 拉”的错误用法</h2>
<p dir="auto">当大家想紧急发生产时，很自然会做出一个看似合理、实则危险的动作：</p>
<ul>
<li>从 <code>develop</code> 拉一个 <code>hotfix/*</code> 分支</li>
<li>然后 <code>hotfix/* -&gt; master</code> 发生产</li>
</ul>
<p dir="auto">问题在于：<strong>如果 hotfix 的基线来自 develop，它本质上等价于“把 develop 发布到生产”</strong>。<br />
这就必然把别人还未准备好的改动一起带进去。</p>
<blockquote>
<p dir="auto">关键原则：<br />
<strong>生产修复（hotfix）必须从“生产基线”分出来</strong><br />
也就是：<strong><code>hotfix/*</code> 必须从 <code>master</code> 拉</strong>，而不是从 <code>develop</code> 拉。</p>
</blockquote>
<hr />
<h2>4. 共识目标：我们到底要的是什么制度</h2>
<p dir="auto">我们需要一套“成本不高、不会出错”的制度，解决两个核心问题：</p>
<ul>
<li><strong>生产发布可控</strong>：能明确“这次上生产到底包含哪些提交”</li>
<li><strong>多仓库链路稳定</strong>：上游是什么分支，下游就尽量跟随；不跟随也要有可预测的 fallback</li>
</ul>
<p dir="auto">换句话说：让 <code>master</code> 真的“受保护”，让生产发布变成一个<strong>可管理动作</strong>。</p>
<hr />
<h2>5. 建议落地方案（推荐，成本最低且最符合治理闭环）</h2>
<h3>5.1 分支定位（长期分支 + 临时分支）</h3>
<ul>
<li><strong><code>master</code>（生产基线，受保护）</strong>
<ul>
<li>只允许 MR 合入</li>
<li>对应 production/staging 发布（手动）</li>
</ul>
</li>
<li><strong><code>develop</code>（集成基线，建议受保护）</strong>
<ul>
<li>通过 MR 合入，减少“无意破坏”</li>
<li>对应 test 环境（自动）</li>
</ul>
</li>
<li><strong>允许临时分支（不等于分支爆炸，而是必要的“隔离器”）</strong>
<ul>
<li><code>feature/&lt;KEY&gt;-&lt;slug&gt;</code>：从 <code>develop</code> 拉，合回 <code>develop</code></li>
<li><code>hotfix/&lt;KEY&gt;-&lt;slug&gt;</code>：<strong>从 <code>master</code> 拉</strong>，合回 <code>master</code> 发生产</li>
</ul>
</li>
</ul>
<blockquote>
<p dir="auto">这并不是回到复杂 GitFlow，而是最小集合：<br />
“两个长期分支 + 两类临时分支”，用来解决“只发布一部分”的刚需。</p>
</blockquote>
<h3>5.2 发布路径（把“整合发布”和“紧急修复”分开）</h3>
<ul>
<li><strong>整合发布（develop 当前整体可发布）</strong>
<ul>
<li>走 <code>develop -&gt; master</code> MR</li>
<li>staging 验证后，手动 production</li>
</ul>
</li>
<li><strong>紧急修复（develop 不可整体发布）</strong>
<ul>
<li>从 <code>master</code> 拉 <code>hotfix/&lt;KEY&gt;</code></li>
<li>只把必要提交带过去（见下一节 <code>cherry-pick</code>）</li>
<li><code>hotfix -&gt; master</code> 上生产</li>
<li><strong>回灌</strong>：再做一次 <code>master -&gt; develop</code>，避免修复丢失或未来重复出现</li>
</ul>
</li>
</ul>
<h3>5.3 <code>cherry-pick</code> 的角色：解决“只想上其中几个提交”</h3>
<p dir="auto">当修复已经在 <code>develop</code> 做完，但 <code>develop</code> 夹杂其他人改动时：</p>
<ul>
<li>不再用 <code>develop -&gt; master</code> 解决</li>
<li>而是从 <code>master</code> 拉 <code>hotfix/&lt;KEY&gt;</code>，然后对 <code>develop</code> 上属于本次修复的提交执行 <code>cherry-pick</code><br />
这样生产只包含你要发布的那几个提交，不会把别人的未完成工作带上去</li>
</ul>
<hr />
<h2>6. 多仓库下游触发：FANOUT_BRANCH 的意义与补充规则</h2>
<p dir="auto">在多级触发（A-&gt;B-&gt;C）里，容易出现“分支漂移”：<br />
每一跳都用 <code>CI_COMMIT_BRANCH</code> 触发下游，会导致链路不可预测。</p>
<p dir="auto">现有文档已定义唯一原则：</p>
<ul>
<li><strong><code>FANOUT_BRANCH</code> 贯穿整条触发链路</strong></li>
<li>上游传了就沿用；没传就等于 <code>CI_COMMIT_BRANCH</code></li>
</ul>
<h3>补充建议：同名分支优先 + 不存在则回落 master（可选增强）</h3>
<p dir="auto">当上游是 <code>hotfix/&lt;KEY&gt;</code> 时，下游可能未创建同名分支。理想策略是：</p>
<ul>
<li>下游存在同名分支：触发同名分支</li>
<li>下游不存在：回落到 <code>master</code></li>
</ul>
<p dir="auto">这类 fallback 要做到“稳定不报错”，通常需要在触发前做一次“分支存在性判断”（脚本/机制层面），避免触发直接失败。是否引入该增强，视团队对稳定性与实现成本的取舍决定。</p>
<hr />
<h2>7. 这套制度能解决什么、代价是什么</h2>
<h3>能解决</h3>
<ul>
<li><strong>生产发布可控</strong>：不会再“合并一次把所有人带上生产”</li>
<li><strong>责任边界清晰</strong>：谁的改动、哪个 Key、进了哪些仓库、是否已合 master 一目了然</li>
<li><strong>发布更安全</strong>：<code>master</code> 真正成为“受保护的生产基线”</li>
</ul>
<h3>需要付出的代价</h3>
<ul>
<li><strong>合并与回灌变成日常管理工作</strong>（但这是“可控发布”的必要成本）</li>
<li>要求改动尽量小步快跑，否则合并冲突会指数级上升</li>
</ul>
<hr />
<h2>8. 执行清单（请团队统一遵守）</h2>
<ul>
<li><strong>分支来源</strong>
<ul>
<li><code>hotfix/*</code> 必须从 <code>master</code> 拉</li>
<li><code>feature/*</code> 从 <code>develop</code> 拉</li>
</ul>
</li>
<li><strong>发布生产</strong>
<ul>
<li>非紧急：<code>develop -&gt; master</code>（前提是 develop 已声明为可发布集合）</li>
<li>紧急：<code>hotfix/* -&gt; master</code>（必要提交用 <code>cherry-pick</code> 精准带入）</li>
</ul>
</li>
<li><strong>回灌</strong>
<ul>
<li>hotfix 发布后必须 <code>master -&gt; develop</code></li>
</ul>
</li>
<li><strong>治理约束</strong>
<ul>
<li>分支名、commit、MR 标题必须带合法 Key（<code>ZD/TG/REQ</code>）</li>
<li><code>master</code> 必须受保护，只允许 MR</li>
</ul>
</li>
</ul>
<hr />
<h2>9. 下一步（建议）</h2>
<ul>
<li><strong>把以上规则固化进团队文档</strong>（branch-rules）</li>
<li><strong>在 CI 中增加最小校验</strong>（例如：hotfix MR 目标必须是 master；关键作业基于分支类型区分环境）</li>
<li><strong>结合“按 Key 聚合查询”工具</strong>：每天/每周形成“哪些 Key 已合 master、哪些仍在 develop/feature”的报告，降低遗漏风险</li>
</ul>
<hr />
<p dir="auto">如果你希望我把这篇公告进一步“贴近你们仓库的现实参数”（比如：当前只允许 <code>master/develop</code> 还是允许 <code>feature/hotfix</code>；哪些环境 job 是自动/手动；是否需要下游分支 fallback），你回复两句话即可：</p>
<ul>
<li><strong>你们最终是否允许临时分支 <code>feature/*</code>、<code>hotfix/*</code>？</strong></li>
<li><strong>下游触发 fallback（同名分支优先，不存在回落 master）要不要做成强制能力？</strong></li>
</ul>
]]></description><link>https://talk.loda.net/post/51</link><guid isPermaLink="true">https://talk.loda.net/post/51</guid><dc:creator><![CDATA[admin]]></dc:creator><pubDate>Sun, 11 Jan 2026 00:57:43 GMT</pubDate></item></channel></rss>