CHANGELOG 管理:记录项目变更历史

FreeGuideOnline 最新 2026-07-01

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[Unreleased]

Added

  • 新增用户头像上传功能。

Changed

  • 将配置文件格式从 JSON 切换为 YAML。

Fixed

  • 修复登录页面在移动端的布局错乱问题。

[1.2.0] - 2025-03-15

Added

  • 增加深色模式支持。
  • 新增搜索结果的过滤选项。

Fixed

  • 修复内存泄漏导致的长时间运行崩溃问题。

[1.1.0] - 2025-02-10

Changed

  • API 响应结构现在统一包含 statusdata 字段。

Removed

  • 移除已弃用的 getUserLegacy 接口。

[1.0.0] - 2025-01-01

Added

  • 首次公开发布。

要点说明:
- **`## [Unreleased]`**:记录尚未发布的变动,发布时再改为具体版本号和日期。
- **版本号链接**:可选的,通常将版本号链接到对应的 Git 标签比较页。
- **分组名称**:保持英文,但描述可以用项目的自然语言;分组建议固定用 `Added`、`Changed`、`Deprecated`、`Removed`、`Fixed`、`Security`。

---

## 如何手动编写 CHANGELOG

即使是小团队或个人项目,手工维护一个格式清晰的 CHANGELOG 也不算重负。遵循以下流程即可:

1. **在开发分支上持续记录**:每当完成一个新特性、重构或修复,立即在 `## [Unreleased]` 下对应的分组中增加一行描述。
2. **发版前整理**:
   - 将 `## [Unreleased]` 改为具体的版本号和日期,例如 `## [1.3.0] - 2025-04-01`。
   - 再次检查描述是否准确、无遗漏。
   - 按照贡献量或重要性调整条目顺序(通常最重要或面向用户的新功能放最前面)。
3. **创建新的 `[Unreleased]`**:在顶部重新添加空的 `## [Unreleased]` 区块,为下一次迭代做准备。
4. **提交并打标签**:将 CHANGELOG 的修改与代码一同提交,并打上对应版本的 Git 标签。

---

## 自动化生成工具

当项目规模变大、提交历史很丰富时,完全手动写 CHANGELOG 会变得乏味且容易出错。可以借助工具从 Git 提交记录自动生成初始版本,然后再手工校对。

### 基于 Conventional Commits 的工具

如果你的团队遵循 [约定式提交](https://www.conventionalcommits.org/zh-hans/v1.0.0/) (Conventional Commits),那么自动化会非常准确。常见的工具包括:

| 工具 | 特点 | 使用命令示例 |
|------|------|--------------|
| **standard-version** | 自动化版本升级、CHANGELOG 生成、打标签 | `npx standard-version` |
| **semantic-release** | 全自动发布管道,根据 commit 决定版本号并生成 CHANGELOG | 在 CI/CD 中配置 |
| **git-cliff** | 高度可配置,支持自定义模板 | `git cliff -o CHANGELOG.md` |
| **commitizen** + **cz-conventional-changelog** | 交互式填写规范化的 commit,配合生成工具 | `git cz` |

以 `standard-version` 为例,它读取 `fix:` 和 `feat:` 前缀的提交,分别归入 `Fixed` 和 `Added`,并自动计算 SemVer 版本号。一条典型的工作流:

```bash
# 发布一个新的次要版本
npx standard-version --release-as minor

# 推送代码和标签
git push --follow-tags origin main

配置示例:git-cliff

如果你喜欢高度自定义的模板,git-cliff 是个不错的选择。在项目根目录创建 cliff.toml

[changelog]
header = "# Changelog\n\n"
body = """
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | upper_first }}
{% for commit in commits %}
- {{ commit.message | upper_first }}
{%- endfor %}
{% endfor %}
"""
footer = ""

然后运行 git cliff -o CHANGELOG.md,即可生成结构清晰的 CHANGELOG。


最佳实践

  • 坚持一个版本一个 ## 小节,不要把所有历史写成一大段长文。
  • 描述改动对用户的意义,避免只写内部模块名。例如:“修复数据库连接池耗尽”优于“修改 getConnection 超时时间”。
  • 破坏性变更务必醒目:在 Changed 分组中可再加 **BREAKING**: 前缀,或直接使用 ### Breaking Changes 子分组。
  • 不要重复 Git 提交信息:CHANGELOG 应该是对提交的有意义聚合和提炼。
  • 与版本管理结合:如果使用 Git,建议在 CHANGELOG 中为每个版本加上对应的比较链接,例如:
    [1.2.0]: https://github.com/user/repo/compare/v1.1.0...v1.2.0
    
  • 保持最新:养成在合并 Pull Request 时同时更新 CHANGELOG 的习惯,可以把它作为 PR 模板的必填项。

常见误区

  1. 丢下 CHANGELOG 只写 Release Notes:发布页面(如 GitHub Releases)不能替代项目内的 CHANGELOG.md,后者可被随代码一起浏览、离线阅读。
  2. 把全部 commit 日志直接转储:杂乱无章的提交历史对最终用户几乎没有价值。
  3. 跳版本写日志:每个版本都应该有自己的记录,哪怕是简单的“仅内部重构”。
  4. 忽略日期:没有日期的版本会让用户无法判断安全和及时性。

结合 GitHub Actions 自动更新

可以设置一个 GitHub Actions 工作流,在每次推送标签时自动生成 CHANGELOG 并更新 Release。以下是一个使用 release-drafter 的简化模板:

name: Release Drafter

on:
  push:
    branches:
      - main

jobs:
  update_release_draft:
    runs-on: ubuntu-latest
    steps:
      - uses: release-drafter/release-drafter@v6
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}