Community编程与开发github.com

xz-dev/下游分支维护技能

维护上游跟踪的下游分支以及达到 PR 质量的补丁栈,避免逐渐漂移为硬分叉。

下游分支维护技能 是什么?

此技能提供了一套结构化的方法,用于维护与上游仓库保持同步的下游分支。其核心目标是防止下游分支逐渐演化成独立且难以合并的硬分叉。技能定义了一套清晰的分支模型,包括专门用于独立补丁的“补丁分支”、用于处理多补丁集成兼容性问题的“临时兼容补丁分支”,以及承载自动化任务(如 CI/CD 和发布流程)的“ci 维护分支”。该技能强调所有补丁都应保持可独立构建、测试和审查的状态,以便最终能作为上游 PR 提交。它包含一个自动同步工作流,通过定期从最新的上游提交重构集成结果,并执行严格的验证步骤,确保生成的代码和构件既完整又可用。该技能适用于 Claude Code、Cursor 等 AI 编码助手,帮助开发者管理复杂的上下游同步挑战。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add xz-dev/downstream-fork-maintain-skill

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

下游分支维护

概述

维护下游分支的目的,不是让它逐渐与上游脱节,演变成一个独立演化的硬分叉。而是持续维护一组可用的、可构建的、可测试的补丁集合。

下游分支跟随上游演进,同时在 PR 尚未合并、上游维护者繁忙或补丁小众但紧急时,及时向用户提供包含这些特性和修复的代码及构件。它不是一个静态的补丁存档,而是一个分发渠道,补丁在其中真正运行并持续处于验证之下。

一个可用的集成结果也让更多人能够自由测试上游 PR、下游补丁以及他们自己的更改。随着上游向前发展,持续构建、测试和审查这些补丁,可以降低 PR 因落后于上游而腐烂的风险,提前暴露问题,并帮助变更最终流入上游。

核心目标

  • 防止下游分支演变为与上游长期分离的硬分叉。
  • 持续跟随上游发展,而不是仅保留某一时间点的静态分支。
  • 让每个补丁都保持独立可构建、可测试、可审查,并适合提交或作为 PR 持续维护。
  • 通过主分支或发布分支提供可以直接使用的代码和构件。
  • 让用户能够针对真实的集成结果测试 PR、补丁以及他们自己的变更。
  • 尽早发现补丁与上游之间的冲突,保持 PR 可合并,并帮助补丁最终流入上游。

分支模型

仓库决定实际的分支名称。不要假设默认分支、远程名称或托管平台。

上游主分支

上游主分支是每次重建的起点。在同步前获取其最新状态,并使用特定的上游提交作为当前构建的基线。

下游的主分支或发布分支绝不能成为补丁的新基线。补丁应始终明确其相对于上游的变更内容。

补丁分支

将每个独立的补丁维护在自己的分支上,并使其达到正常的 PR 标准:

  • 保持范围聚焦,提交和说明清晰明了。
  • 包含足够的测试以演示行为。
  • 使其在当前上游可独立构建和审查。
  • 只声明必要的依赖,避免与其他下游补丁绑定。
  • 使其适合直接作为上游 PR 提交或用于现有 PR 的持续维护。
  • 通常,补丁分支不应修改由上游维护者集中维护的发布文件,例如 CHANGELOG。必要的文档更改应限于与该补丁直接相关的代码注释、API 文档和实现说明。在维护分支上集中维护下游补丁列表和发布说明。

补丁分支是该补丁的长期事实来源。发布分支上的集成提交不是补丁的唯一副本,且不得携带仅存在于发布历史中的临时修复。

临时兼容补丁分支

当多个补丁独立应用时没有问题,但组合后产生不属于任何单个 PR 分支的构建、测试或行为冲突时,在 tmp/patch/<name> 分支上维护一个兼容性补丁。

此类分支仅针对特定补丁组合的下游兼容性问题。不要将修复强制放入某个独立的 PR 分支,也不要让它成为一个新的长期特性分支。它必须声明其依赖的补丁、在顺序中的位置、所验证的组合行为以及何时可以退役。

在 ci 分支的同步编排中,将 tmp/patch/<name> 紧接在其依赖的补丁之后放入顺序列表中。如果之前的 Git 合并已经产生了未解决的文本冲突,后续的兼容性分支无法跨越该冲突。在这种情况下,ci 编排必须在重建继续之前,在发生冲突的步骤处显式应用相应的兼容性处理;仅将分支追加到列表末尾是不够的。

ci 维护分支

当下游分支需要承载自动化(如 GitHub Actions)时,维护一个独立的 ci 分支。如果仓库已有等效分支,则保留其名称。此分支是下游分支的发布覆盖层,负责:

  • 下游特定的 CI/CD、打包、发布以及仓库配置。
  • 自动获取上游、按顺序集成补丁、重建发布分支并安全推送。
  • 额外的下游单补丁测试和多补丁集成测试。
  • 下游的 README、补丁列表、发布说明以及任何下游特定的维护说明。
  • 已启用常规补丁和 tmp/patch/<name> 分支的固定集成顺序。

如果用户或下游分支有超出此通用工作流程的维护要求,请将其保存在 ci 分支上的下游自有文件 MAINTAIN.md 中。该文件应说明如何维护此特定分支,并记录未来的维护人员和自动化必须遵循的任何特殊规则。将其视为仓库特定的指南:在更改补丁分支、同步编排或发布历史之前阅读它,并在这些要求发生变化时保持其更新。

当可能会忽略这些特殊维护规则时,在 ci 分支的 README.md 中添加一个简洁的提示,链接到 MAINTAIN.md。将详细规则保留在 MAINTAIN.md 中,而不是在 README 中重复。

ci 分支可以集中承载下游发布自动化,但不要将产品行为补丁混入其中。运行时更改应保留在适合独立构建、测试和提交上游 PR 的分支上。

此技能包括当前实践中使用的 GitHub Actions 文件:ref/upstream-sync.yml。当需要 GitHub 自动同步时,将其复制作为 .github/workflows/upstream-sync.yml 的起点,然后根据目标仓库调整上游地址、默认/发布分支、ci 和补丁列表、tmp/patch/<name> 顺序、同步计划、下游自有文件、密钥和检查。该文件保留了其原始项目中的项目特定配置,没有经过审查不得启用。

在配置 schedule 时,首先询问用户每天同步应在哪些小时运行。除非工作流显式设置了支持的 timezone,否则 GitHub cron 默认使用 UTC。不要将任务安排在每小时的整点(0 分):GitHub 官方文档 指出每小时开始时负载较高,因此计划的任务可能会在高负载下延迟甚至丢弃。为了进一步避免常见的五分钟间隔,不要使用 5 的倍数,如 10、15、20、30、40 或 45。从 1-59 分钟中随机选择一个不是 5 的倍数的分钟数,并在工作流中将其写为固定值,例如运行 python -c 'import secrets; print(secrets.choice([m for m in range(1, 60) if m % 5]))'。这里,“随机”仅适用于生成配置时;不要使工作流在每次运行时等待动态随机延迟。

主分支或发布分支

主分支或发布分支从最新的上游开始,按固定顺序集成维护分支和所需的补丁分支。它提供完整的代码、构建、测试和发布构件。

此分支仅代表当前下游集成结果。它不是任何补丁的长期维护来源。问题可能首先在此处复现和分析,但修复必须返回到所属的补丁或维护分支,之后必须重新生成集成结果。

在发布历史中,每个补丁应显示为一个清晰、可计数的集成提交,使得下游补丁的数量以及下游分支落后于上游的提交数量都清晰可见。

工作流程

1. 检查当前状态

开始之前,阅读仓库自身的维护和贡献说明,包括下游的 MAINTAIN.md(如果存在)以及指向它的任何 README 提示。检查工作目录、远程仓库、当前分支、上游关系以及现有的同步和发布流程。保留或绕过任何未提交的用户工作;未经许可不得清理或覆盖。

2. 在编码前检查上游 Issue 和 Pull Request

在实现任何新请求或编写代码之前,搜索上游的问题跟踪器和 pull request,以查找相关的讨论或实现。检查已打开和已关闭的 issue,以及已打开的、草稿的、已关闭的和已合并的 PR;不仅要搜索请求的确切措辞,还要搜索相关的组件名称、错误消息和合理的同义词。跟踪链接的 issue、审查、提交和替代 PR,直到建立当前状态。

使用结果选择下一步操作:

  • 如果上游已经实现了该需求,则验证适用的版本和行为,然后再决定是否仍需要下游更改。
  • 如果存在一个活动的 issue 或 PR 涉及该问题,则优先贡献于、测试、更新或临时携带该工作,而不是创建一个不知情的重复。
  • 如果早期的方法被拒绝、回滚或取代,则在提出新的实现之前理解其给出的原因。
  • 将相关的上游链接和结论记录在工作计划、补丁说明或 PR 描述中,以便决策保持可审查性。

当存在相关的上游 issue 或 PR 时,不要直接进入实现阶段。首先确定它们的实际状态、范围、决策、未解决的问题、审查反馈、实现状态以及与用户请求的关系。然后为用户综合相关的上游信息,而不是转发原始链接列表。清楚地解释学到了什么、它如何影响当前的假设和计划,以及原始请求的哪些部分仍然是必要的。

如果该调查产生了可能改变工作范围、方法、优先级、所有权、兼容性策略或必要性的新发现,则显式询问用户是否应更改计划。在用户确认是保留还是修改计划之前,暂停实现。不要根据上游讨论默默重新解释请求。

不要仅仅因为一次精确术语搜索没有结果就开始实现。首先进行合理的搜索;如果没有找到相关的讨论或实现,说明该结果并继续。

3. 在完整的集成结果上复现问题

首先在当前的主分支或发布分支上复现问题,以确认它在用户实际运行的补丁组合中是如何发生的。

在分析过程中,区别对待:

  • 上游本身的问题。
  • 某个独立补丁的问题。
  • 补丁之间的集成问题;如果不属于任何单个 PR,则放入 tmp/patch/<name>。
  • CI、打包、同步或下游文档中的问题。

4. 定位并修复属主分支

找到负责该行为的补丁分支,并在该分支上完成修复和测试。如果问题涉及多个补丁之间的兼容性,则创建或更新 tmp/patch/<name>。如果问题涉及发布自动化或其他下游维护工作,则修改 ci 分支。

不要仅将冲突修复或产品修复提交到主分支或发布分支。这将在下次从上游重建时丢失,并且会阻止补丁被独立审查。

5. 保持补丁的独立可用性

遵循仓库约定,将补丁更新到最新的上游,在补丁分支上解决冲突,并运行该补丁所需的构建和测试。

确认它不依赖发布分支中的隐藏更改,并且仍然可以独立解释、审查和作为一个 PR 提交。如果已经存在上游 PR,也对其进行更新,并继续根据上游反馈进行维护。

6. 重建主分支或发布分支

再次获取最新的上游,从一个特定的上游头部创建一个干净的候选分支,然后按 ci 分支声明的固定顺序集成发布覆盖层、常规补丁和所需的 tmp/patch/<name> 分支。

每个常规补丁和临时兼容补丁应该在发布历史中产生自己清晰的集成提交。仓库可以使用 squash 合并或项目建立的等效方法,但结果应易于审查和计数。

7. 验证可用结果

针对完整的候选版本运行仓库所需的检查,至少涵盖:

  • 每个补丁本身的聚焦测试。
  • 组合多个补丁后的集成行为。
  • CI、打包和下游文档是否来自正确的分支。
  • 用户实际获取的代码或构件是否与验证通过的提交对应。

仅在候选代码和构件均通过所有必需验证后,才更新远程的主分支或发布分支。

自动同步

自动同步的目的是定期从新的上游头部重新生成可用的下游发布结果,而不是在旧的发布分支上不断累积修复。

同步过程应:

  1. 使用仓库接受的并发控制机制,防止两个同步或发布过程同时更新同一分支。
  2. 获取最新的上游、ci 分支、所有已启用的常规补丁以及所有 tmp/patch/<name> 分支。
  3. 从该运行显式选择的上游提交创建一个干净的候选分支。
  4. 按固定顺序集成下游发布覆盖层、常规补丁和临时兼容补丁,每个集成步骤都创建一个清晰的提交。
  5. 针对候选分支运行构建和测试,包括每个补丁的专用测试以及组合后的集成测试。
  6. 如果验证失败,则中止并通知用户,而不更新任何远程引用。
  7. 如果验证成功,则将候选分支安全地推送到远程的主分支或发布分支。

自动同步工作流不应包含对补丁本身的修复。任何修复都必须在属主补丁或兼容性分支上完成,然后通过下一次同步重新集成。

相关技能