首页
/ Changelog category (leave one):

Changelog category (leave one):

2026-09-05 13:58:35作者:谭伦延

Changelog category (leave one):

  • New Feature
  • Experimental Feature
  • Improvement
  • Performance Improvement
  • Backward Incompatible Change
  • Build/Testing/Packaging Improvement
  • Documentation (changelog entry is not required)
  • Critical Bug Fix (crash, data loss, RBAC)
  • Bug Fix (user-visible misbehavior in an official stable release)
  • CI Fix or Improvement (changelog entry is not required)
  • Not for changelog (changelog entry is not required)

Changelog entry (a user-readable short description of the changes that goes into CHANGELOG.md):

...


规则是:**只保留一个类别(删掉其余列表项),并在所选类别要求时撰写 changelog 条目**。标注 "changelog entry is not required" 的三个类别(Documentation、CI Fix or Improvement、Not for changelog)可以跳过条目;这一"免条目类别"集合与 CI 侧 [pr_labels_and_category.py](https://gitcode.com/GitHub_Trending/cli/ClickHouse/blob/fd8e52de9e81a4c9ee46556f76dddadc81275f97/ci/jobs/scripts/workflow_hooks/pr_labels_and_category.py?utm_source=gitcode_repo_files) 中 `NO_CHANGELOG_REQUIRED_LABELS`(`pr-not-for-changelog`、`pr-ci`、`pr-documentation` 等)的定义是一致的,模板类别字符串与脚本中 `LABEL_CATEGORIES` 的映射表逐字对应,说明模板选项就是 CI 解析的输入契约。

### 一份优秀正文的完整示例

技能文档引用了官方仓库 PR #96110 的正文作为标杆,其中 changelog 条目部分完整如下:

Changelog category (leave one):

  • Backward Incompatible Change

Changelog entry:

The semantics of the do_not_merge_across_partitions_select_final setting were made more obvious. Previously, the feature could be automatically enabled when the setting was not explicitly set in the configs. It caused confusion repeatedly and, unfortunately, led to some issues in production. Now, the rules are simpler: do_not_merge_across_partitions_select_final=1 enables the functionality unconditionally. If do_not_merge_across_partitions_select_final=0, then automatic is used only if the new setting enable_automatic_decision_for_merging_across_partitions_for_final=1 and not used otherwise. To preserve the old behaviour as much as possible, the defaults were set to do_not_merge_across_partitions_select_final=0 and enable_automatic_decision_for_merging_across_partitions_for_final=1.


The backward-incompatible part is that if someone has do_not_merge_across_partitions_select_final=0 explicitly set in the configs, it no longer protects against the use of automatics. I'm open to discussion on whether we should conservatively default to disabled automatics.


这个示例值得逐点拆解:

- 条目完整讲清了三件事:**旧行为**(未显式配置时功能可能被自动开启)、**新行为**(显式 `1`/`0` 的语义、新设置的作用条件)、**默认值选择**(如何尽量保留旧行为);
- 分隔线 `---` 之后还有补充讨论——这是合法的:审阅者看得到,但**只有空行之前的 changelog 条目会进入 CHANGELOG**;
- 结尾主动邀请讨论不兼容点的处理方式,体现了"写出来供决策"的姿态。

## Changelog 条目:写给升级用户,不是写给开发者

技能文档对 changelog 条目的核心定位是:**它是最终进入公开发布 CHANGELOG 的内容,要写给"正在升级、正在扫描哪些变更与己有关"的用户看**。PR 链接与作者署名由工具自动追加,不要手写。

### 解析格式:CI 实际如何截取你的条目

技能文档声称条目收集逻辑位于 [tests/ci/changelog.py](https://gitcode.com/GitHub_Trending/cli/ClickHouse/blob/fd8e52de9e81a4c9ee46556f76dddadc81275f97/tests/ci/changelog.py?utm_source=gitcode_repo_files),这一点可以在源码中得到验证(`Description.parse` 相关的解析逻辑,见 [tests/ci/changelog.py#L325-L398](https://gitcode.com/GitHub_Trending/cli/ClickHouse/blob/fd8e52de9e81a4c9ee46556f76dddadc81275f97/tests/ci/changelog.py?utm_source=gitcode_repo_files#L325-L398)):

```python
# All following lines until empty one are the changelog entry.
while i < len(lines) and lines[i]:
    entry_lines.append(lines[i])
    i += 1
entry = " ".join(entry_lines)

据此可以确认文档所述格式规则:

  • 脚本从 ### Changelog entry:(或 Short description 等变体,正则还容忍 #>*_ 前缀和加粗标记)表头之后开始收集,直到第一个空行为止
  • 收集到的多行用空格 join 成一个段落字符串——所以模板里条目可以跨多行,最终变成单段;
  • 空行会终止收集,空行之后的一切(如 --- 后的补充讨论)被忽略。

此外,源码还揭示了几个文档未明说、但对撰写者有用的自动规整行为:

  • 开头的 - / * 项目符号会被剥掉(tests/ci/changelog.py#L391-L393);
  • 首字母小写会被自动大写;
  • 末尾缺句号会被自动补上 .tests/ci/changelog.py#L435-L437);
  • 若条目为空,类别会被标记为 NO CL ENTRY,条目退化为 NO CL ENTRY: '<PR标题>'——即漏写条目的 PR 会以 PR 标题代替条目出现在 CHANGELOG 中,而代码注释表明这种情况"本应被 CI 的描述检查拦住"。

由此得到的撰写结论与文档一致:把条目写成一个段落——不用项目列表、段内不留空行;若要在条目后补充讨论,用空行(或 ---)隔开。

时态、长度、具体性

  • 时态:混用完全可以且自然。Added XFix a case where...The X setting is now Y 都是真实 CHANGELOG 中的写法,不必强行统一现在时。
  • 长度:与影响面匹配。一个新的小函数可以一句话;改默认值或向后不兼容的行为,需要多少句就写多少句,包括用户要做什么来适配
  • 具体性:永远点名"具体改了什么"。绝不写 Fix a bugImprove performance 而不说具体对象。

文档给出的四个真实 CHANGELOG 范例,按影响面从低到高排列,是极佳的长度标尺:

  1. 聚焦新增,一句话足够:

    Add xxh3_128 hashing function.

  2. 一句话但带足上下文:

    DATE columns from PostgreSQL are now inferred as Date32 in ClickHouse (in previous versions they were inferred as Date, which led to overflow of values outside a narrow range). Allow inserting Date32 values back to PostgreSQL.

  3. 默认值变更,附完整迁移说明:

    Deduplication is turned ON for all inserts by default. It was OFF before for async inserts and for MV's, but it was ON for sync inserts. The goal is to have the same defaults for both ways of inserts. If you have deduplication explicitly disabled on your cluster, you have to explicitly set deduplicate_insert='backward_compatible_choice' to keep the old behavior.

  4. 新能力说明,细到用户能判断何时该用它:

    Added OPTIMIZE <table> DRY RUN PARTS <part names> query to simulate merges without committing the result part. It may be useful for testing purposes: verifying merge correctness in the new version, deterministically reproducing merge-related bugs, and reliably benchmarking merge performance.

另一条硬性规则:对向后不兼容变更,必须同时说明旧行为、新行为、以及如何在可能时恢复旧行为(上面 do_not_merge_across_partitions_select_final 的完整示例就是这一规则的标准执行)。

如果存在对应 issue,在条目末尾引用:Closes #XXXXXFixes #XXXXX

值得补充的是,仓库还有一份面向更广受众的条目写作指南 docs/changelog_entry_guidelines.md,其要求与技能文档高度互补:以用户而非开发者为第一读者(不只说 what,还说 why/how it affects the user)、控制在 1–5 句、用反引号包裹设置名/函数名/SQL/格式名/数据类型、遵循"它做什么 → 为什么对用户重要 → 如何(如需)使用"的可扫读格式。技能文档与这份指南结合使用,基本覆盖了条目撰写的所有维度。

类别选择如何驱动 CI 行为

从源码结构看,changelog 类别不只是发布说明的分组标签,它还直接驱动 CI 流水线。pr_labels_and_category.py 中维护了类别到 label 的双向映射 LABEL_CATEGORIES / CATEGORY_TO_LABEL,例如:

  • Backward Incompatible Changepr-backward-incompatible
  • Critical Bug Fix (crash, data loss, RBAC) or LOGICAL_ERRORpr-critical-bugfix(该 label 还出现在 AUTO_BACKPORT 集合中,意味着关键修复可触发自动 backport 流程)
  • Not for changelog (changelog entry is not required)pr-not-for-changelog
  • Documentation (changelog entry is not required)pr-documentation

同时 NO_CHANGELOG_REQUIRED_LABELS 集合明确列出无需 changelog 条目的类别:pr-not-for-changelogpr-cipr-documentationpr-autogenerated-docs。脚本还实现了基于 Levenshtein 距离的模糊匹配(_levenshtein 函数),用于容错匹配模板中的类别措辞变体——这意味着类别字符串尽量与 模板 原文逐字一致是最稳妥的做法,但不要指望"大致相似"总能被正确识别。

tests/ci/changelog.py 一侧,类别解析还有两个可确认的行为:Bug fix 类类别会被归一化为 Bug Fix (user-visible misbehavior in an official stable release) 写入 changelog;backport PR 的条目会被自动加上 Backported in #N: 前缀。

应当避免的写法(What to avoid)

技能文档单列了一节"会让 PR 更难读、或传递出低投入信号"的模式,完整继承如下:

  • fix(scope): / feat(): / chore(): —— ClickHouse 不使用 conventional commits;
  • This PR ... 开头任何小节——直接描述改动即可;
  • 含糊标题:Fuzzer fixesFix bugImprovements —— 永远说具体是什么;
  • 用 Markdown 表格对比"改前/改后行为",除非确实有用;
  • 通篇完全平行的句式——自然变换措辞。

AI 协作署名与确认偏好

技能文档明确表态:公开提及 AI 协助是被接受的。commit 中加 Co-Authored-By: 或在 PR 描述中致谢均可——ClickHouse 对 AI 辅助开发持开放态度。这与仓库内其他 AI 相关设施(如 .github/copilot-instructions.md)的存在相互印证。

关于应用流程:创建或更新 PR 前,技能会检查用户记忆中是否存有确认偏好;若无偏好且会话是交互式的,会询问一次"是否每次应用前给你过目,还是每次直接执行",然后把答案存入记忆并长期遵循;非交互会话则直接执行、不询问。

Fork 与上游:PR 必须开在规范仓库上

文档最后一节处理 fork 场景:如果当前仓库是 fork(判断方式:git remote get-url origin 不包含 ClickHouse/ClickHouse),PR 必须指向上游规范仓库,具体做法是给 gh pr create 传参:

gh pr create --repo ClickHouse/ClickHouse --head <fork-owner>:<branch>
登录后查看全文
热门项目推荐
相关项目推荐