Files
2026-08-25 14:42:26 +08:00

6.6 KiB
Raw Permalink Blame History

版本号与 tag

确定权威版本来源

按项目实际构建链路寻找版本来源,不要遍历到一个看起来像版本号的字符串就修改。优先级:

  1. 项目发布文档或 .release-policy.yaml 明确声明的文件。
  2. 项目明确由 Git tag 或 VCS metadata 派生构建版本时,以 tag 规则作为发布版本来源, 不要为了发布凭空新增或修改版本文件。
  3. 构建、打包或运行入口直接读取的清单,例如 VERSIONpackage.jsonpyproject.tomlCargo.toml 或语言工具链的版本配置。
  4. 由权威文件生成的镜像文件、锁文件或发布元数据。
  5. 最近稳定 tag,用于确定当前已发布版本、更新说明范围和发布历史。

记录每个权威文件的当前值和更新方式。多个权威来源不一致时停止,不要选择修改时间最新 的文件,也不要只改其中一个。

配置声明了版本文件时,它们必须使用仓库相对路径。拒绝绝对路径、.. 和解析后逃出目标 worktree 的 symlink;修改前确认规范化后的准确路径。不要用 glob 或模糊搜索结果执行 批量替换。

选择目标版本

项目已有 CalVer、单调构建号、独立包版本或自定义方案时继续使用,不要迁移到 SemVer。 项目没有规则且只有一个协调版本时使用 SemVer:

  • 不兼容的公开 API 或行为变化增加 major。
  • 向后兼容的新功能增加 minor。
  • 向后兼容的修复增加 patch。

根据实际兼容性判断,不要只凭 commit 前缀自动升级。项目明确采用 Conventional Commits 或已有版本工具时,可以把它们的结果作为项目规则。破坏性影响无法确定时给出建议并请 用户确定准确版本。

预发布版本沿用项目格式;没有格式时使用 -alpha.N-beta.N-rc.N。正式 tag 默认不加入 build metadata。不要从带 build metadata 的 tag 推断兼容性顺序。

独立多包版本、多个维护分支和 release train 不属于默认单版本流程。无法确定一个目标 版本时停止并说明需要增加包或发布线维度。

规范化与渲染

内部始终分别记录规范版本、分支名和 tag 名。默认 SemVer 的规范版本不含 v,例如 用户输入 v1.6.0 时规范化为 1.6.0;版本文件写入 1.6.0,再将它代入 release/v{version}v{version}。不要把完整 tag 名直接代入 {version}

项目采用自定义前缀或非 SemVer 时,以项目版本来源定义规范值,以 branch/tag pattern 定义展示形式。规范化结果无法唯一确定时停止并让用户确认。

判断是否需要同步版本

直接读取计划 release commit 中的权威版本来源。版本文件已经是目标值,或者项目明确由 tag 派生版本,且发布说明不要求写回仓库时,不产生仓库修改,直接进入 tag 发布。

只有权威版本文件、生成文件或仓库内 CHANGELOG 必须变化时,才进入准备版本流程并使用 分支/PR。不要为了制造发布提交而触碰与构建、运行或项目发布规则无关的文件。

同步版本

仅在判断存在必要仓库差异后,在准备版本的分支中一次性更新所有权威版本来源、生成文件 和项目要求的 CHANGELOG。运行项目自己的版本更新工具时,先检查它会修改哪些文件,避免 隐式发布、提交或上传。

提交前确认:

  • 所有权威来源都是目标版本。
  • 生成文件与来源一致。
  • CHANGELOG 或发布说明描述的是本次实际变更。
  • 项目构建和测试读取到了新版本。

生成更新说明

以最近一个适用于当前发布线的稳定 tag 为起点,以 release commit 为终点,结合项目 CHANGELOG、已合并 PR/MR 和实际 diff 生成更新说明。首次发布使用项目声明的发布基线; 没有声明时核对完整可达历史,并在说明中明确这是首次发布。

正式版本的 tag message 使用以下固定格式;内容必须基于本次实际变更,并与 CHANGELOG 或 PR/MR 发布说明保持一致:

<tag>

Summary:
- <一句话概括本版本>

Changes:
- <变更 1>
- <变更 2>

Validation:
- <验证命令及结果>

Base commit: <release commit>

SummaryChangesValidationBase commit 四个字段必须全部存在,不能只有 版本号、提交标题或空 message。没有仓库 CHANGELOG 时,也必须按此格式补齐字段。 Changes 只写入实际存在的新增、变更、修复、维护或文档变化;破坏性变化、迁移步骤和 已知限制存在时必须单独标明。没有实际功能变更时不得伪造条目,应明确说明这是文档、 打包或发布元数据修订。不要生成空标题或模板占位。Validation 写入本次实际执行或已经 确认通过的验证命令及结果,不要编造未执行的检查。Base commit 必须是本次 release commit。

每条说明都要能追溯到范围内的提交、PR/MR 或项目 CHANGELOG。提交消息和 PR/MR 文本只 作为待核对素材,不能覆盖实际 diff,也不能把范围外变化写入本次说明。创建 tag 前先 生成并检查完整 message,再冻结;tag 已推送后不再修改。

验证 release commit

准备版本路径以代码托管平台返回的 merged commit 为准;直接发布路径以计划中锁定的远端 commit 为准。获取远端 base 或允许的维护分支后,确认 release commit 可从对应远端引用 到达,并直接读取该 commit 中的版本文件。不要用当前 checkout 或 feature worktree 中的 文件证明 release commit 内容。

正式 tag 必须满足:

  • tag 名按项目格式由目标版本唯一生成。
  • tag 必须是 annotated tagmessage 必须是冻结后的完整更新说明,最少包括 SummaryChangesValidationBase commit;不能只有版本号、提交标题或空 message。禁止 lightweight release tag。
  • 远端没有同名 tag,或同名 tag 已经准确指向本次 commit。
  • annotated tag 显式指向 release commit。
  • 项目要求签名时,push 前已成功创建 signed tag,并在本地验证签名通过;不可用或失败 时停止,不得改用 unsigned tag。
  • 推送后从远端重新读取 tag object,核对对象类型和完整说明,再将 annotated tag 解引用 到 commit。

展开 tag pattern 后用 git check-ref-format refs/tags/<tag> 校验。把 tag 和 commit 作为 独立 argv 传递,不拼接 shell 字符串。

tag 已在远端指向其他 commit、是 lightweight tag、缺少更新说明或说明不一致时停止。 不要 force push、删除或移动已发布 tag;由维护者决定撤销发布或创建新的修订版本。