更新了,但没人知道:vibe 项目的 Changelog 与版本发布沟通实战
AI 让 vibe 项目一周发五版,但用户感知到的版本数是零。本指南从 Keep a Changelog 规范选型、0.x 版本号的诚实艺术、breaking change 沟通四件套,到应用内弹窗/邮件/X/公众号/Product Hunt 的渠道话术矩阵、三类条目的好坏写作对比、公开路线图三选一,外加可直接抄的 React Changelog 时间线组件、RSS 生成脚本与每周/双周发布 SOP——把「更新了」翻译成「被知道」。

上周三深夜,你的 coding agent 一口气修了 14 个 bug,加了 3 个功能,还顺手重构了整个设置页。周四早上你打开应用商店,「版本更新说明」那一栏写着:bug 修复与性能改进。你盯着这行字,像盯着孩子成绩单上的「该生表现良好」——信息量为零,情绪价值也为零。
这就是 vibe 项目的通病:更新了,但没人知道。AI 让你一天能发三个版本,可用户感知到的版本数是零。迭代速度和感知速度之间的剪刀差,正在悄悄吃掉你的留存——用户不是因为你没更新而离开,而是因为他们以为你「好久没更新了」。
这篇指南讲的就是怎么补上这一课:Changelog 不是写给开发者的 git log,而是产品叙事。它回答的不是「改了什么代码」,而是「这周的产品为什么值得你再打开一次」。下面是从规范选型、版本号艺术、渠道话术、写作模板、公开路线图,到可直接抄的代码和发布 SOP 的完整实战。
为什么 vibe 项目更需要 Changelog
传统团队一个月发一版,changelog 是锦上添花;vibe 项目一周发五版,没有 changelog 就是灾难。四个理由,一个比一个现实。
第一,信任赤字:AI 写的代码,用户天然多一分怀疑
用户不知道、也不关心你的代码是不是 AI 写的,但他们能感觉到「这个产品变得好快」。变化太快而解释太少,人会本能地不安:昨天还好好的功能,今天按钮挪了位置,明天 API 返回变了。Changelog 是你对用户说的「变化都在掌控之中」——每一次解释,都是一次信任存款。反过来,悄悄改、悄悄上线,是信任提款机。
第二,感知速度决定留存,不是迭代速度
做个算术:你一周推了 20 个改进,用户感知到 0 个,等于你这周白干了 90%。很多独立开发者抱怨「功能做了很多,用户就是不回来」,真相往往是用户根本不知道那些功能存在了。Changelog 是把「做了」翻译成「被知道」的唯一廉价通道——比买量便宜,比写博客快。
第三,它是你的营销素材库
Product Hunt 发布帖、X 上的更新 thread、公众号的版本推送,素材都从同一个地方来:一份写得好的 changelog。Linear 的 changelog 经常被转发,Raycast 的更新说明自带 GIF 传播——先有好的 changelog,才有好的发布营销,顺序别搞反。没有 changelog 的发布营销,等于现编现卖,质量全看当天手感。
第四,写给三个月后的你自己
vibe 项目还有个隐形读者:未来的你。AI 一天生成的代码量,顶你手写一个月。三个月后你想知道「这个诡异的兼容逻辑当初为什么加」,git log 里只有 agent 写的 fix: resolve edge case in export flow,等于没说。一份面向用户的 changelog,顺手就是一份「产品决策备忘录」。
一句话判断:如果你上周发的三个版本,用户一个都说不上来你更新了什么,你缺的不是功能,是 changelog。
规范选型:Keep a Changelog × Conventional Commits,什么规模用什么
先把两个最容易搞混的东西分开:Conventional Commits 是写给协作者(和工具)看的提交规范,Keep a Changelog 是写给用户看的变更日志规范。一个管输入,一个管输出。vibe 项目一人团队,最常见的错误是只做了前者——commit 写得整整齐齐,changelog 一片空白。
Keep a Changelog:用户语言的六个抽屉
Keep a Changelog 规定每个版本下只分六类,名字本身就是用户视角:
- Added(新增):新功能,用户能直接用的东西
- Changed(变更):已有功能的行为变化
- Deprecated(废弃预告):将来会删,先打招呼
- Removed(移除):删掉的功能
- Fixed(修复):修掉的 bug
- Security(安全):安全相关修复,单独拎出来是给用户吃定心丸
注意它刻意没有「优化」「重构」「杂项」——用户不关心你重构了状态管理,他只关心「打开变快了」。凡是不能翻译成用户收益的改动,不配进 changelog,扔进 git log 就好。
Conventional Commits:机器可读的提交方言
feat: xxx、fix: xxx、docs:、refactor:、chore:、BREAKING CHANGE: 尾注。这套东西的价值不在「好看」,而在工具能读懂:git-cliff、release-please 这类工具可以直接从 commit 历史拼出一份 changelog 草稿,feat 进 Added,fix 进 Fixed,带 BREAKING CHANGE 的自动标红。
我的实战建议是:让 agent 按 Conventional Commits 写 commit(给它一条 system prompt 就够了),changelog 永远人工改写一遍。工具生成的草稿是「开发者方言」,用户要读的是「人话」。自动生成解决「从无到有」,人工改写解决「从有到好」,两步缺一不可。
选型表:什么规模用什么
- 单人 side project,周更以内:Keep a Changelog 手写 CHANGELOG.md 就够了,别上工具链。Conventional Commits 随缘——让 agent 养成
feat/fix前缀习惯即可,成本几乎为零。 - 一人全职产品,双周有固定发布:Conventional Commits 强制执行 + git-cliff 自动生成草稿 + 人工改写。这是性价比最高的组合,一周多花 20 分钟。
- 小团队 / 开源项目 / 有外部 API 使用者:release-please 全套:commit 驱动版本号、自动打 tag、自动起草 GitHub Release。这时候 changelog 是契约,一点不能马虎。
判断标准就一条:你的改动会不会让别人的代码挂掉。会,就上最严的那档;不会,Keep a Changelog 手写版完全够用。别为了「规范」而规范,vibe 项目的规范是拿来省时间的,不是拿来供的。
给 agent 的两条 prompt:让规范自动执行
vibe 项目的规范不能靠「记得」,要靠 prompt。把下面两段分别塞进 agent 的 system prompt 或项目级 AGENTS.md,规范就从「人工检查项」变成「默认行为」:
【提交规范】
每次完成一个独立改动就提交一次,message 必须用 Conventional Commits:
- feat: 用户可见的新功能;fix: 修 bug;refactor: 重构(无行为变化)
- docs: 文档;chore: 依赖/构建杂务
- 破坏性改动必须在 message 尾部加空行写 BREAKING CHANGE: 说明影响
- message 用英文写,一句话,不超过 72 字符;不要写 "update" "fix bug" 这种空话
【Changelog 草稿】
每次发版前,根据本次 commit 生成 CHANGELOG.md 草稿,要求:
- 只收录用户能感知的改动,重构/依赖升级不进
- 分类用 Added / Changed / Fixed / Security 四类中文名
- 每条一句话,动词开头,写清楚用户在哪能看到这个变化
- 草稿标注 [DRAFT],等我人工改写后再发布
注意第二段最后那句「等我人工改写」——这是整套流程里最重要的一行。agent 生成的永远是草稿,发布按钮只能人来按。changelog 是你产品的脸,别把脸交给自动化的最后一公里。
版本号语义化实战:0.x 时代的诚实艺术
SemVer(semver.org)规则人人都背得出来:MAJOR.MINOR.PATCH,breaking change 升 MAJOR,新功能升 MINOR,修 bug 升 PATCH。但 vibe 项目 90% 的时间活在 0.x,而 0.x 的规则只有一句话:anything MAY change(什么都可能变)。这句话既是护身符,也是陷阱。
0.x 不是免责金牌,是诚实契约
很多人把 0.x 当成「随便改不用负责」的借口:反正 0.x 什么都可能变,用户要骂也只能认。这是对 SemVer 最坏的理解。0.x 真正的意思是:你还处于快速试错期,但试错不等于一声不吭。诚实的做法恰恰相反——0.x 时代更要写清楚每次 breaking change,因为你的早期用户是最宝贵的,他们值得被认真对待。
实操上我推荐「0.x 三件套」:
- 版本号照样认真升:小步快跑也分得清 0.8.1 和 0.9.0 的区别,别学某些项目永远 0.1.0。版本号是给用户的安全感刻度。
- breaking change 照样写迁移说明:哪怕只有三行,「旧写法 → 新写法」对照贴出来。Tailwind CSS v4 发布时(2025 年 1 月)把 breaking change 写成逐条对照表,还配了
@tailwindcss/upgrade自动迁移工具——人家都 4.0 了还这么体贴,你 0.x 有什么理由摆烂。 - 给 0.x 定一个「毕业线」:比如「API 连续三个月没 breaking change」或「有 100 个付费用户」,到了就升 1.0。1.0 不是「完美了」,而是「我敢承诺了」。
什么时候敢升 1.0:三个信号
- 有人为你的产品付费了——付费是最强的稳定承诺,1.0 是对付费用户的交代;
- 有人在你的 API/插件生态上构建东西——这时候 breaking change 的成本从「用户不爽」变成「别人的生意受损」;
- 你自己连续两个月没想砍掉重练核心模块——说明架构基本定型了。
反例是「0.9.9 住了三年」的项目:不敢升 1.0,本质是不敢承诺。用户看得懂这种心虚。
breaking change 怎么沟通不挨骂
先说结论:breaking change 挨骂,从来不是因为你改了,而是因为你没提前说、没给退路、没说人话。四件套缺一不可:
- 提前说(deprecation 期):至少提前一个版本标记
Deprecated,在控制台/界面里打出警告。给用户留的迁移时间,等于你给自己留的口碑。 - 给退路:能给迁移工具就给工具(codemod、自动升级脚本),给不了工具就给「旧版维护到 X 月 X 日」的明确承诺。「直接升,不兼容」是最招骂的写法。
- 说人话:别写「重构了鉴权中间件以符合 OAuth 2.1 规范」,写「登录方式变了:旧的 API Key 还能用到 12 月 31 日,之后请换成 OAuth 登录,3 步搞定,文档在这」。
- 给补偿:breaking change 影响付费用户时,延长一周试用、给一个月折扣,成本极低,效果极好。用户要的不是钱,是「你把我当回事」的态度。
反面教材:某知名开源项目(名字就不点了)在 minor 版本里悄悄改了默认配置,导致大批用户生产环境报错,issue 区炸了 400+ 条。作者的回应是「文档里写了」。文档里写了 ≠ 沟通了。changelog 里用
Changed大标题标出来,再难听的话也少一半。
发布渠道矩阵:一份 changelog,四种讲法
同一份 changelog,扔到不同渠道要用不同的话术。很多独立开发者只写 GitHub Release,然后抱怨「写了没人看」——废话,你的用户又不住在 GitHub 上。渠道矩阵的核心是:按用户的注意力场景,决定信息密度。
应用内更新弹窗:3 秒原则
用户打开应用看到弹窗,耐心不超过 3 秒。只讲三件事:一句话说清最大变化、一张图(新功能截图/GIF)、一个按钮(「试试」/「知道了」)。弹窗里永远只放 Added 里最性感的一条,剩下的让用户点「查看完整更新日志」自己去看。Raycast 是这方面的标杆:每次更新弹窗就是一句话加一张 GIF,点进去才是完整 changelog。
话术示例:「导出终于支持 PDF 了 →」配一张导出菜单的截图。别写「我们很高兴地宣布」,没人高兴,除了你。
邮件更新简报:每月或每版本一封
邮件是唯一「用户会存下来」的地方,适合讲稍微完整的东西。标题公式:版本号 + 最吸引人的那一条,比如「v2.4:深色模式来了,外加 12 个修复」。正文结构固定:1 句开场 → 3-5 条精选更新(每条一句话 + 链接)→ 1 句预告下期。频率上,宁可双周一封有干货,也别周周一封水——退订率是检验水准的唯一真神,超过 1% 就说明你在发垃圾。
X / 公众号:一个讲梗,一个讲故事
这是最容易搞混的一对。X(推特)上是同行和极客,话术可以技术流、可以玩梗:「把导出 PDF 的渲染时间从 8s 干到 0.4s,方法是把 Chromium 换成了……」配代码截图,极客最爱看这个。公众号/博客上是普通用户,话术讲场景:「月底做报销,3 分钟导出一整月账单 PDF」,配操作动图。同一条更新,X 讲「怎么做到的」,公众号讲「对你有什么用」,千万别一篇稿子两边发。
Product Hunt / Show HN 评论区:持续更新的「楼中楼」
发布首日之后,评论区就是你的第二个 changelog。在自己的 Product Hunt 发布帖或 Show HN 帖子下定期回帖更新「What's new since launch」,是成本最低的二次曝光——每一次回帖都会把帖子顶回部分订阅者的时间线。话术要点:感谢当初提建议的人(@ 出来),把他们的建议和你这次的实现挂钩,「你上次说的导出 PDF,这版加上了」。这是把批评者变成 evangelist 的最短路径。
GitHub Releases:写给开发者的完整版
这里是唯一可以「开发者方言」的地方:完整的 Added/Changed/Fixed 列表、breaking change 的迁移代码、贡献者名单(@ 出来,真金白银的社交货币)。如果你的项目有 API 使用者,这里还要加「升级检查清单」。GitHub 从 2021 年起支持「Automatically generated release notes」,一键从 PR 标题生成草稿——拿它当草稿,永远别直接发布,PR 标题是写给 reviewer 的,不是写给用户的。
Changelog 写作模板:三类条目的好坏对比
好 changelog 和坏 changelog 的差距,不在文笔,在信息结构。通用公式先摆出来:动词开头 + 用户视角 + 影响范围 + 行动指引。下面三类条目,每类一组好坏对比,坏的都是真实项目里常见的写法(包括我自己早期写的)。
功能类(Added)
❌ 坏:「新增了导出功能。」——导出什么?在哪?和我有什么关系?四个灵魂拷问一个都答不上。
✅ 好:「报表页现在可以导出 PDF 了:右上角 → 导出 → 选 PDF,模板自动沿用你当前的主题配色。导出的文件带目录书签,打印也好看。」——动词开头(「可以导出」),用户视角(报表页、右上角),影响范围(主题配色、书签),行动指引(三步操作)。
修复类(Fixed)
❌ 坏:「修复了已知问题,提升了稳定性。」——这是应用商店里烂大街的尸体话术。用户读完只知道一件事:你不想告诉他你修了什么。
✅ 好:「修复了 Safari 下日期选择器点不开的问题(感谢 @liam 反馈)。如果你之前遇到过,现在刷新页面即可,不用更新应用。」——点名感谢反馈者(社交货币),说清影响范围(Safari 用户),给出行动指引(刷新即可)。修 bug 的 changelog 是最好的用户运营:让用户看到「我提的问题被修了」,比任何积分体系都管用。
安全类(Security)
❌ 坏:「安全更新,建议升级。」——用户心想:出什么事了?你不说我更慌。
✅ 好:「修复了一个权限漏洞:协作成员此前可能看到他人的草稿文档,现已修复,所有用户建议更新到 v2.4.1。这次不涉及密码和支付信息泄露。」——说清「发生了什么 + 影响谁 + 要做什么」,但绝不写漏洞利用细节(那是给攻击者的教程)。最后一句「不涉及密码和支付信息」是定心丸,专门回答用户最害怕的那个问题。
自检清单:每条写完问自己三句话——我妈能看懂吗?用户知道要点哪里吗?不看这条会错过什么?三问都通过,才算一条合格的 changelog。
公开路线图怎么做:Notion / Linear / GitHub Discussions 三选一
changelog 讲的是「过去」,路线图讲的是「未来」。公开路线图的本质不是功能许愿池,而是承诺管理:让用户知道你在往哪走,让他们敢把自己的工作流押在你身上。三个工具,三种性格,选错比不做好。
Notion:最快,适合非技术用户多的产品
建一个公开页面,看板视图三列:计划中 / 开发中 / 已发布。每条卡片一句话描述 + 状态标签,完事。优势是零学习成本、可以嵌入官网、手机上也好看;劣势是互动弱(评论要登录 Notion)。适合:效率工具、消费级应用、用户不太写代码的产品。实操要点:页面顶部加一句「路线图会变,changelog 说了算」,给自己留政策空间;每月归档一次已发布,避免页面变成垃圾场。
Linear:适合已经在用 Linear 管研发的团队
Linear 的 Roadmap 视图可以一键公开分享,开发进度和公开路线图是同一份数据源——不用维护两套,这是它最大的杀招。状态(Todo/In Progress/Done)自动同步,你在 Linear 里拖一下卡片,公开页面就更新了。劣势:免费版功能有限,且风格偏「工程师向」。适合:SaaS、开发者工具、已经用 Linear 的小团队。
GitHub Discussions:适合开源 / 开发者向产品
用 Discussions 的投票功能做需求收集:每个想法一个帖子,用户用 👍 reaction 投票, maintainer 打上 planned / in-progress / shipped 标签。优势是离代码最近、讨论质量最高,还能顺手把贡献者转化成代码贡献者;劣势是对非技术用户有门槛。适合:开源项目、API 产品、SDK。实操要点:每月发一帖「本月路线图同步」,把 Discussions 里的高票需求和实际排期对上号——这是开源项目维持信任的核心仪式。
三条铁律(用哪个工具都一样)
- 只放已立项的,不放「想想而已」:路线图上的每一条,都应该是你真的打算做的。画饼一时爽,被翻旧账火葬场。
- 每条必须有状态,没有「永远计划中」:一条需求在「计划中」躺超过 6 个月,要么做,要么诚实地标「暂不考虑」并说明原因。用户能接受「不做」,不能接受「装死」。
- 路线图和 changelog 互相链接:路线图里「已发布」的条目,链接到对应版本的 changelog;changelog 里提一句「这条来自路线图投票第 3 名」。闭环一旦形成,用户会开始主动给你投票——你的需求池就有了免费水源。
代码实战:可复用的 Changelog 时间线组件 + RSS 生成脚本
光讲道理不够,下面是两段可以直接抄的代码思路。第一段是一个 React + TypeScript 的 Changelog 时间线组件:从你自己的 /api/changelog 拉数据,按版本分组渲染,支持分类徽标和「复制版本链接」。第二段是一个 Node 脚本:扫描 changelog/ 目录下的 markdown 文件,生成 RSS/Atom feed——让你的更新能被 RSS 阅读器和「更新聚合」类服务订阅。
Changelog 时间线组件(React + TS)
设计要点:数据结构先行。每个版本是一个对象,条目带分类,后端可以是静态 JSON,也可以是 CMS。组件只负责渲染,不碰数据源,这样以后从 JSON 换成数据库不用改 UI。
// types.ts —— 数据结构先定好,前后端共用
export type ChangeKind = 'added' | 'changed' | 'deprecated' | 'removed' | 'fixed' | 'security';
export interface ChangeEntry {
kind: ChangeKind;
text: string; // 一句话人话,已按写作模板写好
link?: string; // 可选:指向文档或演示
}
export interface Release {
version: string; // "2.4.0"
date: string; // "2026-10-08" (ISO)
pinned?: boolean; // 大版本置顶
entries: ChangeEntry[];
}
// kind → 徽标颜色,一套映射全站通用
export const KIND_META: Record<ChangeKind, { label: string; color: string }> = {
added: { label: '新增', color: '#16a34a' },
changed: { label: '变更', color: '#2563eb' },
deprecated: { label: '废弃预告', color: '#d97706' },
removed: { label: '移除', color: '#dc2626' },
fixed: { label: '修复', color: '#7c3aed' },
security: { label: '安全', color: '#b91c1c' },
};
// ChangelogTimeline.tsx
import { useEffect, useState } from 'react';
import { Release, ChangeEntry, KIND_META } from './types';
function EntryRow({ entry }: { entry: ChangeEntry }) {
const meta = KIND_META[entry.kind];
return (
<li style={{ marginBottom: 8 }}>
<span style={{
display: 'inline-block', fontSize: 12, color: '#fff',
background: meta.color, borderRadius: 4, padding: '1px 8px', marginRight: 8,
}}>{meta.label}</span>
<span>{entry.text}</span>
{entry.link && (<a href={entry.link} style={{ marginLeft: 8 }}>了解更多 →</a>)}
</li>
);
}
export default function ChangelogTimeline() {
const [releases, setReleases] = useState<Release[]>([]);
const [error, setError] = useState(false);
useEffect(() => {
// 数据源:/api/changelog 返回 Release[],按 version 倒序
// 可以是静态 JSON 文件,也可以接 CMS / 数据库
fetch('/api/changelog')
.then((r) => { if (!r.ok) throw new Error('bad status'); return r.json(); })
.then(setReleases)
.catch(() => setError(true));
}, []);
if (error) return <p>更新日志加载失败,请稍后再试。</p>;
if (!releases.length) return <p>正在加载更新日志…</p>;
return (
<div>
{releases.map((rel) => (
<section key={rel.version} id={`v${rel.version}`} style={{ marginBottom: 40 }}>
<h3 style={{ display: 'flex', alignItems: 'baseline', gap: 12 }}>
v{rel.version}
{rel.pinned && <span style={{ fontSize: 12 }}>⭐ 大版本</span>}
<span style={{ fontSize: 13, color: '#666' }}>{rel.date}</span>
<a href={`#v${rel.version}`} style={{ fontSize: 12 }}>复制链接</a>
</h3>
<ul style={{ listStyle: 'none', paddingLeft: 0 }}>
{rel.entries.map((e, i) => <EntryRow key={i} entry={e} />)}
</ul>
</section>
))}
</div>
);
}
三个细节决定这个组件好不好用:每个版本有锚点(客服和用户吵架时直接甩链接);security 条目永远红色置顶(上面的代码里按数组顺序渲染,所以写数据时把 security 放最前);移动端徽标不换行错位(inline-block + margin,别用 float)。数据源建议:早期直接放 public/changelog.json 静态文件,发布时顺手改一个文件就行;等有 CMS 再换 API,组件不用动。
RSS/Atom feed 生成脚本思路(Node)
为什么还要 RSS?因为你的 changelog 值得被订阅:用户把 feed 扔进阅读器,更新自动推送;一些「产品更新聚合」站点也会抓你的 feed,等于免费分发。脚本逻辑很简单:约定 changelog/v2.4.0.md 这种文件命名,文件名即版本号,文件头三行写日期和标题,正文就是条目。
// scripts/build-feed.mjs —— node scripts/build-feed.mjs > public/feed.xml
import { readdirSync, readFileSync } from 'node:fs';
const SITE = 'https://yourproduct.com';
const files = readdirSync('changelog').filter(f => f.endsWith('.md')).sort().reverse();
const items = files.map((f) => {
const version = f.replace('.md', '');
const raw = readFileSync(`changelog/${f}`, 'utf8').split('\n');
const date = raw[0].replace('date:', '').trim(); // 第一行:date: 2026-10-08
const title = raw[1].replace('title:', '').trim(); // 第二行:title: v2.4.0 深色模式来了
const body = raw.slice(3).join('\n').trim();
return { version, date, title, body };
});
const esc = (s) => s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
let xml = `<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"><channel>
<title>YourProduct 更新日志</title>
<link>${SITE}/changelog</link>
<description>YourProduct 的版本更新与发布说明</description>`;
for (const it of items) {
xml += `
<item>
<title>${esc(it.title)}</title>
<link>${SITE}/changelog#v${it.version}</link>
<pubDate>${new Date(it.date).toUTCString()}</pubDate>
<description>${esc(it.body)}</description>
</item>`;
}
xml += '\n</channel></rss>';
console.log(xml);
把这个脚本挂进 CI:每次发布打 tag 时跑一遍,feed.xml 跟着静态站点一起部署。然后在 changelog 页面 head 里加一行 <link rel="alternate" type="application/rss+xml" href="/feed.xml">,阅读器就能自动发现。全程 30 行代码,零依赖——vibe 项目的 changelog 基建,就该是这个量级:够用、好维护、不用为了「规范」引入三个新服务。
发布节奏 SOP:每周 / 双周检查清单
最后是 SOP。changelog 最大的敌人不是写得烂,是没节奏——想起来写一次,忙起来三个月没动静。固定节奏的发布,是信任的复利:用户会形成「这家每周四都有更新」的预期,预期本身就是留存。
每周发布(适合迭代快的 vibe 项目)
- 周一:定本周发布范围。从 agent 上周的 commit 里挑「用户能感知」的改动,列进 CHANGELOG.md 草稿。判断标准:这条写出来,我妈能看懂它有啥用吗?看不懂就别进。
- 周三:冻结功能,跑一遍核心流程冒烟测试(登录、支付、核心功能三件套)。vibe 项目最容易翻车的就是「agent 改了 A,崩了 B」,冒烟测试 10 分钟,能拦掉 80% 的低级事故。
- 周四发布日:按顺序执行——打 tag → 跑 feed 生成脚本 → 更新 changelog 页面 → 发应用内弹窗(只放最性感的一条)→ 发 X 更新帖 → 回复 Product Hunt/Show HN 评论区。顺序别反:先让 changelog 可访问,再去各渠道吆喝,否则用户点进来的链接是 404。
- 周五:看数据。弹窗点击率、更新采用率(多少用户升到新版)、客服工单里有没有「更新后 XXX 坏了」。有 breaking change 的投诉,24 小时内必须回,哪怕先回一句「收到了,周一给方案」。
双周发布(适合有付费用户、求稳的产品)
在每周版的基础上加三条:第一周周五发「下期预告」邮件(路线图里挑 2-3 条,吊胃口);发布前加一轮「更新说明 review」——找一个非技术朋友读一遍 changelog,他看不懂的地方重写;breaking change 必须提前一个版本 deprecation,双周节奏下没有「这周说下周改」的余地,至少提前 14 天。
紧急热修复通道
线上 P0 故障不走正常节奏:修完立刻发 patch 版本,changelog 里 Fixed 条目第一句写「影响范围 + 是否需要用户操作」。模板:「v2.4.2 紧急修复:今日 14:00-14:25 部分用户导出失败,现已恢复,无需更新应用,刷新页面即可。」——热修复的 changelog 要回答用户最慌的三个问题:我受影响了吗?我需要做什么?现在好了吗?
节奏建议:从双周开始,别一上来就周更。vibe 项目的诱惑是「我一天能发三版」,但发布节奏是给用户看的,不是给 agent 看的。稳定的双周,比时有时无的周更,更能建立信任。等你的 SOP 跑顺了,再加速不迟。
四个真实反模式:changelog 是怎么写死的
最后列四个我见过(也犯过)的反模式,帮你避坑:
- git log 直出型:「fix: resolve race condition in worker pool」「chore: bump deps」。这是写给机器看的,不是给人看的。agent 生成的 commit message 再整齐,也代替不了一句人话。
- 报喜不报忧型:只写 Added,从不写 Removed 和 breaking change。用户迟早会发现功能没了,那时候你的 changelog 信用直接破产。删功能要大大方方写,附上替代方案,用户反而更信任你。
- 版本号玄学型:心情好升个 minor,心情不好升个 patch,0.1.0 用三年。版本号是承诺刻度,不是装饰。实在拿不准就记住:用户要重新学东西 = minor 起步,用户代码会挂 = major。
- 一次性装修型:产品发布那天精心写了一版 changelog,之后再也没更新过。changelog 是连续剧,不是电影海报。接受「先丑后美」:第一版只有三条一句话,也比空白强一百倍,节奏先跑起来再优化文笔。
结语:Changelog 是产品叙事,不是 git log
回到开头那句话:Changelog 不是写给开发者的 git log,而是产品叙事。git log 回答「代码怎么变的」,changelog 回答「产品为什么值得被继续使用」。vibe 时代,写代码的成本趋近于零,稀缺的是「让用户感知到变化」的能力——而 changelog 就是这项能力里最便宜、ROI 最高的工具。
从今天开始,做三件小事:第一,在仓库根目录建一个 CHANGELOG.md,按 Added/Fixed 六分类写;第二,让你的 agent 提交信息带上 feat:/fix: 前缀;第三,下次发布时,把最性感的一条更新做成应用内弹窗。一个月后回来检查:如果用户能说出你上周更新了什么,这篇指南就没白写。
更新了,就要让人知道。沉默的迭代,等于没迭代。
相关文章

Auth 会涨价、免费层会下线、大厂亲儿子也会关门。一人团队没有法务和备选供应商谈判筹码,唯一的盔甲是:给每个外部依赖打分定级,给每个核心依赖写一页逃生预案。本文给出可直接套用的分级矩阵、预案模板、选型十问,以及 Parse、Heroku、Auth0 三个真实翻车案例的解剖。

vibe 项目最大的死法不是做得烂,而是上线那天没人知道。这篇首日作战手册包含:上线前 14 项检查清单、T 日 24 小时五个动作节点的节奏表、Product Hunt / Show HN / X / 小红书四平台文案模板、预热弹药库(等候名单、build in public、KOL 内测)、评论区作战话术、三级流量预案(Vercel/Cloudflare 速配),以及决定产品值不值得继续的五个漏斗数字。

一人团队流量小,更要懂实验设计。这篇实战指南给 vibe 开发者一套小流量实验框架:三大误区(样本量幻觉、过早看结果、只测 UI 颜色)、一句话假设模板与北极星/护栏指标、样本量估算表与实验周期公式、30 行 Next.js Feature Flag 中间件与三档灰度策略、5 个经典坑的真实翻车案例、PostHog/GrowthBook/自研的成本账,以及一页纸实验复盘模板。