ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Carbon Language 提案 p001190 解析:PR 由“评审人合并“的协作模型设计、取舍与落地

Carbon Language 提案 p001190 解析:PR 由“评审人合并“的协作模型设计、取舍与落地 Carbon Language 提案 p001190 解析:PR 由评审人合并的协作模型设计、取舍与落地【免费下载链接】carbon-langCarbon Languages main repository: documents, design, implementation, and related tools. (NOTE: Carbon Language is experimental; see README)项目地址: https://gitcode.com/GitHub_Trending/ca/carbon-lang本文基于 Carbon Language 仓库中的已接受提案 p001190: Reviewer-merged PRs,完整还原该提案要解决的核心问题——当仓库向完全公开开放后,没有合并权限的外部贡献者如何提交代码——以及项目最终选择鼓励评审人合并这一 fork-and-pull 变体模型的论证过程。读完本文,你可以掌握:共享仓库模型与 fork-and-pull 模型的差异与适用边界、五种候选方案(含两人规则)的优缺点权衡,以及该决策在 代码评审文档、拉取请求工作流文档 和 CODEOWNERS 中落地的具体机制,并理解这些流程设计如何服务于 Carbon 的社区文化目标。一、问题:作者自合并模型无法扩展到公开贡献者提案 p001190 的 Problem 部分开门见山:Weve been having authors merged PRs, but thats not going to work when we get contributors who dont have merge access. We need a solution.也就是说,Carbon 此前一直让 PR 作者自己合并自己的拉取请求。这个做法在项目还是小圈子协同时成立,但一旦仓库对公众开放,大量外部贡献者将没有任何合并权限,作者自合并的流程会直接失效,项目必须定义一套替代机制。二、背景:LLVM 的倾向与两种 git 协作模型提案的 Background 部分交代了两个关键背景:LLVM 社区的立场。LLVM 倾向于作者合并(author merge),理由是存在构建机器人(build bots)被打断的风险:如果合并后出现问题,由作者来决定回滚(rollback)还是向前修复(fixing forward)更为合适,因为作者是唯一清楚改动来龙去脉的人。两种主流协作模型。Carbon 当时实际采用类共享仓库模型(shared repository model)——作者直接在共享仓库上开发并合并自己的 PR——但这种模式很难扩展到完全公开的协作场景。另一种主流模型是fork-and-pull 模型:贡献者 fork 仓库后提交流请求,合并由拥有权限的一方执行,这是开源项目中更常见的做法。需要指出的是,谁合并并不只是一个权限问题,它还和 Carbon 的分支管理原则强绑定。在 pull_request_workflow.md 中可以看到:所有开发活动都发生在trunk分支上(trunk-based development),失败时默认回滚到绿色(revert to green),向前修复只有在同样快的时候才被接受(Green tests);拉取请求合入时默认执行squash 合并以保持线性历史(Linear history);已批准的 PR 优先进入merge queue:排队后在全部检查通过时,系统会在trunk之上基于临时分支创建 squash 后的提交并再次跑检查,失败时trunk与 PR 分支均保持原状(Merging a pull request)。从源码结构看,merge queue 的存在意味着合并动作本身已经有一层自动化保护,这为让评审人执行合并降低了风险门槛——即便评审人合并后发现问题,trunk也不会被静默污染,失败会显式暴露并可回滚。三、提案内容:鼓励评审人合并,但保留作者自合并的权利Proposal 部分给出的方案用三句话说清:鼓励评审人在自己觉得合适的时候执行合并(Encourage reviewers to merge when they feel okay doing so);把这个选择权交给评审人(Let reviewers make that choice);作者也可以声明我自己合并(Let authors say theyll merge themselves)。提案将其归类为一种鼓励评审人合并的 fork-and-pull 模型。注意它的措辞是鼓励(encourage)而非强制:这不是只有评审人才能合并的硬规则,而是一种默认倾向加上作者显式退出的机制,从而保留了作者对合并时机的控制。3.1 Details 落地:合并动作的具体规则提案的 Details 一节明确指向 code_review.md 的相应变更,该文档的 Merging pull requests 章节即该决策的落地文本,核心规则包括:合并就绪条件:评审人表示满意(如 LGTM)或已批准 PR 后即可合并;虽然一次批准即可合并,但应给其他评审人留出评论时间以形成共识。作者或评审人都可以合并、都可以解决冲突(Either the author or reviewer may merge and resolve conflicts)。作者自合并的显式声明:作者若希望自己合并,应告知评审人并为 PR 添加DO NOT MERGE标签——这正是提案中Let authors say theyll merge themselves的具体操作形式,用标签机制把口头约定变成了机器可见的信号。合并后责任:执行合并的开发者(无论是作者还是评审人)预期要在线协助处理合并后的问题,无论是向前修复还是回滚。这一点直接回应了 Background 中提到的 LLVM 顾虑——作者合并的优势在于出事有人懂,而该条款通过谁合并、谁值班把同样的责任锚定到了评审人合并的场景上。配套的冲突处理规则见 Fixing conflicts with trunk:PR 有冲突必须先解决才能合并;若 PR 正在评审中,建议等评审基本完成再处理冲突;冲突应通过 merge commit 解决,而不是 rebase(rebase 会破坏 GitHub 的评论关联,且合并时最终会 squash,线性历史目标不受影响)。3.2 合并提交说明:作者保留话语权与谁合并同样重要的是合并提交怎么写。Merge commit descriptions 章节规定:squash 合并时,建议使用 PR 评论区的第一条评论作为 squash 提交的描述,作者应保持其更新,使评审人在合并时无需再改文案;评审人不应自行编辑或改写这条信息,而应像评审代码一样请作者修改(可以给出建议);若 PR 中有评审人的 suggested edits 被应用,GitHub 会在默认提交信息中追加Co-authored-by:行,这些行应保留并附加到初始评论的信息之后。这条规则与提案让作者控制 PR 描述的偏好(见下文替代方案 C)一脉相承:合并提交信息是历史考古的第一手材料,应当以作者的声音记录。四、Rationale:服务于社区与文化目标提案的 Rationale 部分把该方案挂钩到项目目标 goals.md 的 Community and culture 一节,理由是:Defines a process for accepting contributions from developers who dont have merge access.即:它定义了一个接受无合并权限的开发者贡献的流程。这与 goals.md 中对社区目标的表述一致:Carbon 需要支持以全职身份工作的开发者,也需要支持只投入零散时间的兼职者、学生、教师或爱好者(Community and culture),并且需要一个开放、包容的流程,让所有人都能舒适地参与(goals.md)。评审人合并把外部贡献者第一次提交的摩擦降到最低——贡献者不需要等待权限授予,只需要走完评审即可落地,这是流程层面落实包容性的直接手段。从仓库结构看,评审人的可发现性由 CODEOWNERS 文件支撑:文件开头注明本文件仅用于 PR 自动指派,分支保护并不强制执行它,并定义了路由规则——兜底规则把全部路径(*)指派给carbon-language/toolchain-reviewers;关键项目文档(顶层*.md、/LICENSE、/docs/project/evolution.md、/docs/project/goals.md、/docs/project/principles/*、/docs/project/roadmap.md、/proposals/*.md)指派给carbon-language/leads;/toolchain目录指派给carbon-language/toolchain-reviewers。这意味着无论谁发起 PR,评审人都有明确的自动指派目标,而评审人合并模式恰好依赖有一个明确的、有合并权限的评审人在环这一前提——自动指派机制为评审人合并提供了组织保障。code_review.md 的 Who should review? 也强调自动指派只是辅助,开发者可以主动接手未被指派给自己的 PR 以加快评审。五、五种被否决的替代方案及完整权衡提案最有价值的部分是对五个替代方案的逐一分析。以下完整保留原文档的优缺点论证,并补充仓库内的落地证据。5.1 方案 A:永不合并有合并权限者的 PR(最小化评审人合并)规则:告诉评审人,如果 PR 作者有合并权限,评审人就永远不要替作者合并。这同样是 fork-and-pull 模型,但方向相反——最小化而非最大化评审人合并。优点:本提案允许作者退出由评审人合并,但如果作者忘记声明、或评审人没看到声明,就会产生灰色地带;最小化评审人合并可以从根上消除这类情形(即便有强制约束,作者也可能做错)。缺点:依赖评审人自行判断作者是否有合并权限,而评审人可能忘记判断;最可能的后果是外部贡献者不得不主动 提醒才能推进合并。评审人合并不常见,会因不熟练而做得不稳定:无合并权限的贡献者走的是另一套流程,新贡献者因此更可能第一个踩到坑,反过来可能打击贡献积极性。提案还保留了演化余地:未来构建机器人可能带来更多问题,届时可能向这个方向倾斜;也可能在实际协作中自然演化到这里(例如评审人因担心作者提交后需要修复 break 而习惯只与作者协调后合并)。但结论是:目前没有理由把它定为硬规则。5.2 方案 B:授予所有潜在贡献者合并权限(全公开共享仓库模型)规则:向公众授予合并权限,即继续采用共享仓库模型,但从私有共享变为完全公开共享。这样评审人无需考虑权限问题。优点:作者随时可以合并,评审人负担最小。缺点:代码安全严重依赖审批机制,这反过来约束了是否保留 CODEOWNERS这类决策的灵活性。对照当前仓库,虽然 CODEOWNERS 文件自身声明它只用于 PR 自动指派,分支保护并不强制执行它,但分支保护层面仍需要一套与审批强绑定的规则来兜底公开写权限。这种配置对 GitHub 项目而言并不典型,可能比其他方案更让人意外。评审人更难区分高频贡献者和新贡献者:GitHub 提供新提交推送后使陈旧的 PR 审批失效(Dismiss stale pull request approvals when new commits are pushed)选项;为了减轻评审人负担,项目大概率要开启它,但代价是任何变更(可能包括合并提交)都需要评审人重新审批。新手贡献者搞坏东西时可能引发问题:除非理解流程本身成为通过评审的前提,否则不能对新手贡献者有理解流程的期待。5.3 方案 C:允许评审人清理 PR 描述规则:让评审人而不是作者来整理 PR 描述。优点:减少评审往返次数。缺点:PR 描述可能不再是作者自己的声音,令作者感到沮丧。提案的偏好是让作者控制 PR 描述。这一点已经真实写进了 code_review.md:Merge commit descriptions 明确要求评审人不应自行编辑或改写这条信息,而应像评审代码的其余部分一样,请作者来做这些修改(可以附上建议)。5.4 方案 D:只允许作者解决合并冲突规则:合并冲突只由作者解决,不让评审人代劳。优点:降低错误合并的概率,因为作者通常更理解冲突的来龙去脉;有歧义的解决方式可以用作者自己的声音处理:如果一次错误的解决引入了 bug,责任算作者的,而不是责任在评审人、却被归咎到作者头上。缺点:增加评审往返次数:无合并权限的作者提的 PR 会多一轮往返:作者先解决冲突,评审人再合并。最坏情况下,评审人合并前又出现新冲突,PR 会在双方之间来回弹。提案的偏好是尽量压缩评审往返。但作者也诚实地承认:如果评审人的实际习惯是只在没有未决冲突时才合并,那么多一轮往返仍然是现实结果——即最终流程可能事实上退化为方案 D 描述的形态,这是提案中罕见的、对自身方案不利的坦诚推演。5.5 方案 E:对源码变更实施两人规则规则:对源码变更实施两人规则(two-person rule)——作者和评审人都必须看到将要合并的代码。GitHub 可通过新提交推送后使陈旧审批失效的分支保护选项实现,但可能还需要要求每个 PR 有 2 个审批人。优点:提供更强的代码安全性,消除作者或评审人任一方合并了未经另一方审查的变更的情形。缺点:增加评审往返次数:当前评审人可以带着小意见(如改个错别字)就批准;修掉它需要新提交,新提交又需要新的审批;要真正堵住漏洞可能需要为每个 PR 设置 2 个审批人,以防评审人向 PR 推一个提交后自行审批并合并。而要求 2 个审批人还会进一步抬高评审开销。提案的偏好同样是尽量压缩评审往返。5.6 权衡总结把五个方案放在一起,可以看到提案的决策函数非常清晰:在保证安全底线(评审人在环、合并后有人负责)的前提下,最小化评审往返、最小化流程分支。方案 A、D、E 都因增加往返被降级为视情况再议;方案 B 因不典型 权限面过大被否决;方案 C 因剥夺作者话语权被否决。而主方案以鼓励而非强制 DO NOT MERGE标签 合并人合并后值班的组合,同时回应了 Background 中的 LLVM 顾虑(出事有人懂)与 Problem 中的公开化诉求(外部贡献者可落地)。六、配套机制:该提案在整个工作流中的位置6.1 评审与批准的前置条件评审人合并之所以可行,前提是评审流程本身已经规范化。code_review.md 规定了:什么需要评审:对 Carbon 仓库的每一处变更都需要代码评审,code review在 Carbon 中不仅指代码,文档等任何文件都在其范围内(What requires review?);谁来评审:任何人都可以评审,但每个变更至少需要一名有提交权限的开发者评审;按领域分工,Carbon leads 负责提案与关键文档,实现团队负责一般变更(Who should review?);批准的含义:评审人应显式选择 Approve;若只是提供反馈,应显式说明并把评审设为 Comment;还有一条实用技巧——即使有未决的、但修复方式无歧义的小意见,也可以直接批准,作者有疑问随时可以回来(Approving the change)。6.2 僵局处理与升级路径评审人合并模式下,若作者与评审人产生分歧,合并前必须按 Resolving an impasse or conflict 处理:先引入第三人(通常是 owner 或 Carbon lead)或到更广泛的论坛(Discord)征求视角;若仍无法达成方向一致,则走 Escalation——按 Carbon lead 的显式请求,或为解决根本性僵局,变更转入正式提案流程。整个演进与治理机制的完整定义见 evolution.md。而 p001190 本身正是这个提案流程的产物:按 proposals/README.md 的目录规范,已接受的提案以p######-slug.md形式存放,其中数字即提案 PR 号(补零至 6 位);提案正文遵循 template.md 的结构(Problem / Background / Proposal / Details / Rationale / Alternatives considered),并可用 new_proposal.py 初始化。这也解释了为什么一个合并 PR 的流程决策会以提案文档形式长期保留在仓库中:Carbon 的治理目标是为项目为何朝某个方向演化留下清晰的 rationale 记录(evolution.md)。6.3 与分支保护的衔接pull_request_workflow.md 说明:Carbon 的 GitHub 仓库配置为必须经过 PR 和评审才能合并,该规则由分支保护自动强制执行;即便变更看似琐碎,也要走 PR——因为琐碎的变更评审起来同样琐碎。结合 CODEOWNERS 的自动指派与 merge queue 的自动检查,整个链条是:任意贡献者(含无合并权限的外部贡献者) → 创建 PR(自动指派评审人:CODEOWNERS 规则) → 评审(至少一名有提交权限的开发者批准) → 作者或评审人合并(默认鼓励评审人;作者可用 DO NOT MERGE 标签声明自合并) → merge queue:临时分支上 squash 复查,trunk 保持绿色 → 合并人合并后值班,负责 fix-forward 或 rollback七、结论与可借鉴的工程权衡p001190 展示了一个小型开源项目向完全公开过渡时的典型治理难题:如何在不牺牲合并后有人懂、有人负责这一安全底线的前提下,让没有仓库写权限的人也能顺畅贡献。Carbon 的答案不是一次性的权限配置,而是一组相互咬合的流程约定:默认倾向 显式退出:鼓励评审人合并,但用DO NOT MERGE标签保留作者自合并的通道,避免谁合并成为灰色地带;责任跟随合并动作:无论谁合并,合并人都要在提交后可用,这直接继承了 LLVM 关于作者合并的核心理由;自动化托底:CODEOWNERS 自动指派评审人、分支保护强制 PR 评审、merge queue 保证trunk绿色,三者把评审人合并的风险控制在可回滚范围内;以往返次数为决策函数:五个替代方案中,凡实质增加评审往返或被认为不典型的,都被降级或否决,且提案明确保留了向最小化评审人合并(方案 A)未来演化的空间。对读者而言,这套机制的价值不仅在于 Carbon 本身:任何从内部团队走向公开开源、又希望保留线性历史与绿色主干的仓库,都可以直接参考 code_review.md、pull_request_workflow.md 与 CODEOWNERS 这三份文档中可复制的条款设计。【免费下载链接】carbon-langCarbon Languages main repository: documents, design, implementation, and related tools. (NOTE: Carbon Language is experimental; see README)项目地址: https://gitcode.com/GitHub_Trending/ca/carbon-lang创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表