Release Notes 撰写指南
调研来源
综合以下项目的 Release Notes 实践:
| 项目 | 类型 | 特点 |
|---|---|---|
| Zettlr | Electron Markdown 编辑器 | 自然语言概述 + 分类条目 + PR 链接 |
| Clash Verge Rev | Tauri 桌面应用 | 中文撰写 + emoji 分节 + 平台下载链接 |
| SiYuan | Electron 笔记应用 | shields.io badge + issue 链接式 |
| bat | Rust CLI 工具 | 极简分类 + @贡献者 |
| Typst | Rust 排版系统 | 叙述式安全问题 + 贡献者致谢 |
| Claude Code | CLI 工具 | 高频发布,平铺条目 |
| NiceHash | 桌面应用 | 安装指引优先 + 安全验证 |
| eslint | JavaScript Linter | 全条目行内作者括注 (#PR) (author),全自动生成 |
| stablyai/orca | Electron 桌面应用 | GitHub 原生 generate-notes:by @user in #PR + 文末 Contributors 头像墙 |
参考样例:
- Clash Verge Rev v2.5.1: https://github.com/clash-verge-rev/clash-verge-rev/releases/tag/v2.5.1
- Zettlr v4.5.0: https://github.com/Zettlr/Zettlr/releases/tag/v4.5.0
- Obsidian v1.12.7: https://github.com/obsidianmd/obsidian-releases/releases/tag/v1.12.7
- Tauri CLI v2.11.2: https://github.com/tauri-apps/tauri/releases/tag/tauri-cli-v2.11.2
- stablyai/orca v1.4.205: https://github.com/stablyai/orca/releases/tag/v1.4.205
结构选择
发布时先读取 config/projects.yaml:
- 配置了
release_notes.profile:按项目配置指定的结构生成。 - 未配置:桌面应用默认用
desktop-standard,CLI / 库 / Web 按下方适配规则简化。
固定结构
desktop-standard
适用于 Tauri / Electron 桌面应用,尤其是需要用户下载安装包、处理 Gatekeeper / SmartScreen / 终端命令提示的项目。结构固定如下:
- 一句话摘要:正文第一行,使用 blockquote,不写版本标题。
## Highlights:2-5 条用户最关心的变化。## 新增:仅在有新增功能时出现。## 变更:仅在有行为、流程、配置、依赖或发布链路变化时出现。## 修复:仅在有 bug fix 时出现。> [!WARNING]:有安装限制、终端命令、破坏性变更、安全提示时必须出现。## 下载:桌面应用必须出现,列出面向用户的安装包。- 自动更新产物说明:有
.tar.gz/.sig/latest.json时必须说明普通用户无需下载。 ## 贡献者:仅在本版本合入外部贡献者(非维护者)的 PR 时出现,列 handle 与 GitHub 主页链接,条目正文同步做行内标注;无外部贡献者时整节省略(规则见下文「贡献者致谢」)。- 完整变更日志:最后一行使用 compare 链接。
新增 / 变更 / 修复 中没有内容的分区直接省略,不保留空标题。
推荐模板
> 一句话概括本版本核心变更(让用户 5 秒内理解为什么要升级)
---
> [!NOTE]
> 升级提示(仅在有需要时出现)
## Highlights
- **核心特性 1**:简短描述,突出用户价值
- **核心特性 2**:简短描述
---
## 新增
- 功能描述 (#PR号)
## 变更
- 行为变更描述 (#PR号)
## 修复
- 修复描述 (#PR号)
---
> [!WARNING]
> 破坏性变更说明(仅在存在时包含此节)
---
## 下载
| 平台 | 架构 | 文件 |
|------|------|------|
| macOS | Apple Silicon | `<项目>_<版本>_aarch64.dmg` |
| macOS | Intel | `<项目>_<版本>_x64.dmg` |
| Windows | x64 | `<项目>_<版本>_x64-setup.exe` |
> `.tar.gz` + `.sig` 为自动更新专用,无需手动下载。
---
## 贡献者
- [@user](https://github.com/user) — 贡献了某修复(#N;仅列外部贡献者,无外部贡献时整节省略)
---
**完整变更日志**: https://github.com/<owner>/<repo>/compare/<上个tag>...vX.Y.Z设计决策
| 决策 | 依据 |
|---|---|
| 正文不写版本标题 | GitHub Release 页面已经显示 release title,正文再写 # <项目名> vX.Y.Z 会重复;正文应直接从摘要、提示或 Highlights 开始 |
| 中文撰写 | Clash Verge Rev(Tauri 项目)验证中文 Release Notes 完全可行 |
| 顶部一句话 Highlights | Zettlr / Clash Verge 实践:小项目用户不会逐条读 changelog |
| 固定桌面应用结构 | Clash Verge Rev 重视下载区,Zettlr 重视摘要和 changelog,Folia 需要额外稳定呈现 macOS 终端提示 |
| 表格列下载链接 | 比 ### / #### 分级轻量,比纯链接结构化,适合 Folia 这种多平台桌面应用 |
> [!WARNING] 标注破坏性变更 |
GitHub 原生 callout,视觉醒目 |
| 每条附 PR 号 | Zettlr / SiYuan / bat 的共识做法,可追溯 |
| 条目行内标注外部贡献者 | eslint (#PR) (author) / bat (@handle) / GitHub 原生 by @user in #PR 的共识;仅标外部贡献者,维护者自身省略,让致谢信号聚焦 |
| 文末「贡献者」汇总节 | bat「### Contributors」与 GitHub 原生 Contributors 头像墙的做法;放下载区之后、Full Changelog 之前 |
| Full Changelog 比较链接 | Zettlr 的做法,一键查看完整 diff |
贡献者致谢(Attribution)
外部贡献者的 PR 必须在 Release Notes 中致谢——这是社区项目的基本礼仪,漏掉会直接打击贡献者积极性。触发背景:Folia v0.8.1 曾整版遗漏——该版三个修复全部源自同一位外部贡献者(#169 直接合入,#166 / #167 为承接 PR 的原始方案),notes 与 CHANGELOG 均无一字提及。
谁需要致谢
| 对象 | 判定 |
|---|---|
| 直接合入的外部 PR | gh pr list --state merged 的 author login 不在维护者名单(单人项目 = owner 之外的所有人) |
| 被承接的原始 PR | 标题 / 描述含「承接 #N」的 PR,回溯原始 PR 致谢其作者——方案来源同样值得致谢 |
| Co-Authored-By 外部作者 | squash merge 保留了 trailer 时 |
| 不需要致谢 | 维护者自身条目;bot(renovate / dependabot / github-actions[bot]) |
识别命令
# 本版本区间合入的 PR 与作者
gh pr list --state merged --limit 50 --json number,title,author \
--jq '.[] | "\(.number)\t\(.author.login)\t\(.title)"'
# squash commit 里保留的 Co-Authored-By trailer
git log <上个tag>..HEAD --format='%(trailers:key=Co-Authored-By)'标注格式(行内必选,汇总节推荐,可叠加)
| 位置 | 写法 | 出处 |
|---|---|---|
| 条目行内(必选) | - 修复描述 (#169, @Yillan-lamb);承接条目写 - 描述 (#171, 原始方案 @Yillan-lamb #166) |
eslint (#PR) (author) / bat (@handle) / GitHub 原生 by @user in #PR |
## 贡献者 汇总节(有外部贡献者时推荐) |
- [@Yillan-lamb](https://github.com/Yillan-lamb) — iCloud 卸载防护(#169),置于下载区之后、Full Changelog 之前 |
bat「### Contributors」/ GitHub 原生 Contributors 头像墙 |
@user 写法在 GitHub Release 页面会自动渲染为用户链接并给对方发通知——致谢即触达,不需要额外动作。
低成本兜底
担心手写 notes 漏识别外部 PR 时,GitHub 原生生成的贡献信息可直接取用:
gh api --method POST repos/{owner}/{repo}/releases/generate-notes \
-f tag_name=vX.Y.Z -f previous_tag_name=<上个tag>返回 body 含每个 PR 的 by @user 标注与 Contributors 列表;手写项目可只搬 Contributors 段补进 notes(orca 全量采用该格式,是最省维护成本的选择)。
不同项目类型的适配
桌面应用(Tauri / Electron)
默认使用 desktop-standard。下载表格列出各平台安装包。标注"推荐"和"不常用"。自动更新产物(.tar.gz / .sig / latest.json)单独说明。
CLI 工具 / 库
不需要下载表格。改为安装命令:
## 安装
npm install <package>@X.Y.Z
# 或
cargo install <package>Web 应用
不需要下载表格。改为部署说明或 changelog 链接。
高频发布项目(每天/每周)
参考 Claude Code 的极简格式:所有条目平铺在 ## What's changed 下,不做分类。
不需要的内容
- shields.io badge(适合大项目,小项目过于复杂)
- 安全 checksums(除非面向安全敏感用户或用户明确要求)
- Cargo audit / 构建日志(框架层细节,应用层不需要)
- 赞助提示(可选,非必须)
monorepo-skills profile
适用场景:一个 GitHub Release 包含多个子项目的 zip(skill 集合、CLI 工具集、npm 包集等 monorepo 场景)。每个子项目自身维护 CHANGELOG.md 的 semver(如 v1.3.1),发布时统一打 tag 一次性出全部 zip。
结构:
- 标题:直接写
## <Tag>不再加版本前缀(GitHub Release 页面已显示标题) ## 本版包含:列出本次涉及的全部子项目与版本(- item-a v1.2.3:修复 X / 新增 Y)## 下载:说明https://github.com/<owner>/<repo>/releases/latest/download/<item>.zip是稳定 URL,无需指定版本号- 可选
## 更新明细:仅在有重大变更时列
示例:
## v2026.06.30
本版包含(7 个子项目有更新):
- item-a v1.5.3:新增"四步流程"风险清单模板
- item-b v0.9.1:支持 paddle 默认后端
- item-c v1.3.2:修复长文截断 bug
- ...
## 下载
任意子项目直接点 https://github.com/<owner>/<repo>/releases/latest/download/<item>.zip
完整列表见本 release 的 Assets。
完整变更日志:https://github.com/<owner>/<repo>/compare/<上个 tag>...v2026.06.30与 desktop-standard 的关键差异:
| 维度 | desktop-standard | monorepo-skills |
|---|---|---|
| 产物矩阵 | 安装包 + updater + sig + latest.json | N 个 <item>-<semver>.zip |
| 用户入口 | 平台下载表格 | latest/download/<item>.zip 直链 |
| Release Notes 重点 | Highlights + 安装限制(Gatekeeper) | 本版包含的子项目列表 |
| 不需要 | > [!WARNING](除非跨版本破坏性变更) |
不需要 latest.json 说明 |