· Jeff · 教程 · 8 分钟阅读
如何维护更新日志(CHANGELOG):写给下一任开发者的项目说明书
更新日志不是给机器看的 git log,是给「下一个打开你项目的人」看的说明书。这篇讲清 CHANGELOG 的六大原则、六种变动类型、一份可直接抄的模板,以及 Unreleased 工作流、该避开的坏做法,还有怎么和 Conventional Commits 配合把维护成本压到最低。
如何维护更新日志(CHANGELOG):写给下一任开发者的项目说明书
接手一个别人的开源项目、或者三个月后回看自己的库,你最想知道什么?不是「代码怎么写的」,而是**「这个项目一路是怎么变过来的、我现在升级会不会踩坑」**。更新日志(CHANGELOG)回答的正是这个问题。
但很多项目根本没有 CHANGELOG,或者干脆把 git log 导出来充数——那玩意儿是写给机器和提交者的,不是写给用户的。这篇文章把「一份好的更新日志该怎么维护」讲透:核心原则、变动类型、能直接抄的模板,以及怎么用 Unreleased 区块把维护成本压到最低。
适用:独立开发者 / 开源项目维护者 / 团队工程规范 | 更新:2026-09-04
一、先搞清楚:CHANGELOG 是给谁看的
一句话:日志是写给「人」而非「机器」的。这个「人」包括三类:
- 下游用户——想知道升级到新版本会不会破坏现有功能、有没有新特性可尝鲜;
- 下一个维护者(很可能是三个月后的你)——想快速知道每个版本改了什么、为什么改;
- 团队伙伴——发版前 review 变更是否完整、有没有遗漏破坏性改动。
想清楚读者,很多维护决策就顺了:git log 之所以不合格,是因为它充满 merge 记录、语焉不详的 commit 标题,是给人「考古」的原料,不是给人「读」的成品。
二、六大核心原则
- 每个版本有独立入口——一个版本一个
##标题,别把所有改动堆在一个「最近更新」里; - 同类改动分组放置——新增归新增、修复归修复,别混着写;
- 新版本在前,旧版本在后——倒序,读者第一眼看到的是最新变化;
- 包含每个版本的发布日期——
## [1.0.0] - 2026-09-01,让读者能判断版本新旧与节奏; - 注明是否遵循语义化版本规范——文件开头写一句「本项目遵循语义化版本」,读者才知道版本号升降意味着什么;
- 只收录「值得注意」的变更——修了个错别字、内部重构,别往里塞,噪音会淹没信号。
记住:CHANGELOG 不是流水账,是经过筛选的变更摘要。
三、六种变动类型
| 类型 | 含义 | 典型例子 |
|---|---|---|
Added | 新添加的功能 | 新增导出 API、新增配置项 |
Changed | 对现有功能的变更 | 修改默认行为、调整参数签名 |
Deprecated | 即将移除、暂时保留的功能 | 标记旧接口为弃用,给用户迁移时间 |
Removed | 已移除的功能 | 删除弃用满期限的接口 |
Fixed | Bug 修复 | 修复某场景下的崩溃 |
Security | 安全性改进 | 修复漏洞、升级依赖中的安全问题 |
其中 Deprecated 最容易忽略——弃用是「预告」,提前一个版本告诉用户「这个要没了」,升级时用户才知道哪些功能即将不可用,这是好日志的加分项。
四、一份可直接抄的模板
# Changelog
所有值得注意的变更都将记录在此文件中。
格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/),
本项目遵循 [语义化版本](https://semver.org/spec/v2.0.0.html)。
## [Unreleased]
## [1.1.0] - 2026-09-01
### Added
- 新增 XX 功能
### Fixed
- 修复 XX 场景下的崩溃
## [1.0.0] - 2026-06-20
### Added
- 首个正式版本
[unreleased]: https://github.com/you/project/compare/v1.1.0...HEAD
[1.1.0]: https://github.com/you/project/compare/v1.0.0...v1.1.0
[1.0.0]: https://github.com/you/project/compare/v0.1.0...v1.0.0底部那几行是版本对比链接(GitHub 会自动生成 diff 页),配合模板能让读者一键看到某个版本到底动了哪些代码。没有对应上一版时(首版)可以不写对比链接。
五、Unreleased 工作流:把维护成本压到最低
维护 CHANGELOG 最大的阻力是「懒得写」——每次改动都要想着去更新文件,时间一长就荒废了。破解办法是在顶部常驻一个 ## [Unreleased] 区块:
- 平时每完成一个值得记录的改动,顺手写进
Unreleased对应分组; - 发版时,把
Unreleased整块迁移成新版本号## [1.1.0] - 日期,再补一行空的Unreleased留给下一轮。
这样写日志从「发版时补作业」变成「日常顺手记」,每笔改动发生时信息最热、记得最准,发版只是一次拷贝粘贴。
六、该避开的坏做法
- 用 git log 堆砌——提交记录是给人考古的原料,不是成品(前面说过,这是头号坏习惯);
- 无视弃用功能——该标
Deprecated不标,用户升级时被突然移除的功能打懵; - 易混淆的日期格式——统一 ISO 8601(
YYYY-MM-DD),别写2026/09/01、9月1日混着来。
七、进阶技巧
- 命名统一:文件就叫
CHANGELOG.md,放项目根目录,这是社区约定俗成的位置; - 撤下版本:发错版本就加
[YANKED]标记,如## [0.0.5] - 2014-12-13 [YANKED],告诉读者「这个版本有问题别用」,比删掉更诚实; - 可以重写:发现遗漏或分类错误,更新日志完全可以重写——它服务于当下读者,不是不可变的历史档案;
- 和 Conventional Commits 配合:如果提交信息已经按 Conventional Commits 规范写(
feat:/fix:/breaking前缀),CHANGELOG 的Added/Fixed分组基本能一一对应,甚至能用 release-please 这类工具半自动生成。但别把 CHANGELOG 完全外包给工具——工具生成的版本往往缺乏「人味」,重要变更的上下文说明还得自己补。
总结
CHANGELOG 本质是写给下一任开发者和下游用户的项目说明书:倒序、分组、带日期、标弃用、注明语义化版本。别拿 git log 充数,用 Unreleased 区块把维护变成日常顺手记,配合 Conventional Commits 规范能让成本进一步下降。
一个项目如果连一份像样的更新日志都没有,再好的代码也像是把用户丢在黑夜里——版本号告诉你「变了」,CHANGELOG 告诉你「变成了什么样、要不要紧」。
相关文章:
- Conventional Commits:让提交信息成为团队共同语言——CHANGELOG 的上游,提交信息规范了日志才好写
- 用 Git 同步 Obsidian 笔记——把版本管理思维用到笔记上
☕ 如果这篇文章对你有帮助
欢迎请 Jeff 喝杯咖啡,支持我持续分享更多软件技巧~
打赏功能即将上线,先点个赞也是支持 ❤️