用 Commit Message Storyteller 写出有故事的提交信息:awesome-copilot 的叙事式 Conventional Commits 技能实战
【免费下载链接】awesome-copilotCommunity-contributed instructions, agents, skills, and configurations to help you make the most of GitHub Copilot.项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-copilot
导读
本篇文章聚焦 awesome-copilot 仓库中的commit-message-storyteller技能:它能把原始的git diff或口头变更描述,转化为遵循 Conventional Commits 规范、强调"为什么改"而非"改了什么"的叙事式提交信息。读完本文,你将掌握该技能的完整调用流程、提交类型判定表、三部分提交结构(主题行/正文/脚注)、多提交拆分启发式与边界情况处理,并了解它与仓库中gitmoji、conventional-commit等兄弟技能的分工差异。
技能定位:从"改了文件"到"讲了故事"
commit-message-storyteller的核心主张在 skills/commit-message-storyteller/SKILL.md 开头就说得非常直白:它"将原始 git diff 和变更描述转化为清晰、故事驱动的提交信息",目标不是产出update file.js这类流水账,而是让每条提交信息传达意图(intent)、上下文(context)与影响(impact)。
这份技能文件遵循 Agent Skills 规范(docs/README.skills.md 说明每个技能是包含SKILL.md指令文件与配套资源的独立文件夹,按需渐进式加载),配套资源为references/conventional-commits-guide.md——一份可随时查证的 Conventional Commits 速查手册,供模型在生成信息时参考完整类型示例与 scope 规范。
何时启用该技能
SKILL.md的 frontmatter 中定义了技能的触发条件与描述,明确列出以下典型场景:
- 用户说 "write a commit message"、"help me commit" 或 "generate a commit"
- 用户直接粘贴一段
git diff或口头描述代码变更 - 用户问 "what should I commit this as?" 或 "summarize my diff"
- 用户希望为团队或开源项目维护更高质量的提交历史
- 用户正准备提交 Pull Request,需要有意义的提交信息
该技能可从三种输入工作:git diff或git diff --staged的输出、对"改了什么以及为什么改"的描述、以及修改文件列表。
前置准备:获取变更上下文
使用前至少准备以下其中一种输入:
git diff或git diff --staged的输出- 一段对变更内容及原因的说明
- 一份修改文件清单
技能在Quick Reference中给出了获取 diff 的标准命令(这是本仓库其他提交类技能,如 skills/gitmoji/SKILL.md 与 skills/git-commit/SKILL.md,也共同采用的习惯):
# 获取已暂存(staged)的变更,粘贴给 Copilot git diff --staged # 或获取工作区中尚未提交的变更 git diff四步生成流程
第一步:收集变更上下文
技能要求先明确三件事,可由用户提供,也可从 diff 中自动推断:
- 改了什么—— 受影响的文件、函数与逻辑
- 为什么改—— bug 修复、新功能、重构、性能优化等
- 谁/什么触发了这次改动—— issue 编号、用户请求、技术债等
如果用户只提供原始git diff,则应从 diff 中自动提取这些上下文,而非反复追问。
第二步:判定提交类型
将变更映射到 Conventional Commits 的类型,SKILL.md给出完整判定表:
| Type | Use When |
|---|---|
feat | A new feature or capability is added |
fix | A bug or incorrect behavior is corrected |
refactor | Code restructured without changing behavior |
perf | A change that improves performance |
docs | Documentation only changes |
style | Formatting, whitespace, missing semicolons (no logic change) |
test | Adding or updating tests |
chore | Build process, dependency updates, config changes |
ci | CI/CD pipeline changes |
revert | Reverting a previous commit |
详细示例见 references/conventional-commits-guide.md。需要注意的是,该类型表与仓库中 skills/git-commit/SKILL.md 的类型表大体一致,但后者额外列出了build类型(构建系统/依赖变更),这提醒使用者:团队约定决定了类型集合,引用速查手册时以项目实际采用的规范为准。
第三步:按三部分结构撰写提交信息
生成的信息遵循如下结构:
<type>(<optional scope>): <short imperative summary> <body — the story: why this change was made, what problem it solves> <footer — issue refs, breaking change notices>主题行(第一行)规则:
- 使用祈使语气:
add、fix、remove,而不是added或fixes - 最多 72 个字符
- 末尾不加句号
- 冒号后小写开头
正文(故事部分)规则:
- 解释为什么(why),而不是什么(what)——diff 已经展示了"改了什么"
- 描述变更前存在的问题
- 如相关可提及考虑过的备选方案
- 每行控制在 100 字符以内
- 与主题行之间用空行分隔
脚注规则:
- 引用 issue:
Closes #123、Fixes #456、Refs #789 - 标记破坏性变更:
BREAKING CHANGE: <description>
关于破坏性变更,references/conventional-commits-guide.md 补充了两种等价写法——在类型后用!(如feat(api)!: remove v1 endpoints),或在脚注中写BREAKING CHANGE:段落,二者可并用。
第四步:生成输出
在可复制的代码块中产出提交信息,随后用一行通俗英语说明你讲述的故事。SKILL.md给出的示例输出:
fix(auth): prevent token refresh loop on expired sessions When a user's session expired mid-request, the auth middleware was triggering a token refresh, which itself failed validation and triggered another refresh — causing an infinite retry loop that crashed the app. This adds a recursion guard flag that aborts the refresh cycle if a refresh is already in progress, returning a clean 401 instead. Closes #312Story told:A silent infinite loop on session expiry was crashing the app; this stops the cycle early and returns a clean error.
注意这个示例的精妙之处:主题行fix(auth): prevent token refresh loop on expired sessions是一句完整的祈使句;正文讲述"之前为什么崩溃、这次如何修复";脚注Closes #312关联 issue。这正是"讲故事"与"流水账"的分水岭。
一个 diff 拆成多个提交
当 diff 包含逻辑上彼此独立的变更时,技能要求拆分成多条提交信息并明确告知用户。启发式判断如下:
- 用途无关的不同文件 → 很可能应拆成多个提交
- 同一文件但关注点不同(例如 bug 修复 + 重构)→ 建议拆分
- 各部分紧密耦合 → 一个提交即可
这一原则与 skills/git-commit/SKILL.md 的 Best Practices("One logical change per commit",一次提交只包含一个逻辑变更)相互印证,也与 references/conventional-commits-guide.md 反模式表里"misc changes应拆分成独立有意义的提交"的建议一致。
边界情况处理表
| Situation | How to Handle |
|---|---|
| 用户只给了 diff、无其他上下文 | 从文件名和变更符号推断类型与 scope |
| 变更横跨大量文件且主题不明 | 询问:"这是一个逻辑变更,还是多个?" |
| 检测到破坏性变更 | 自动添加BREAKING CHANGE:脚注 |
| 用户说 "keep it short" | 省略正文,只写一个有力的主题行 |
| 没有 issue 编号 | 完全省略脚注 |
配套速查手册:Conventional Commits 参考指南
references/conventional-commits-guide.md是技能自带的验证与扩充实操素材,核心内容包括:
格式定义:
<type>(<scope>): <description> [optional body] [optional footer(s)]完整类型示例(含 scope、正文与脚注):速查手册为每个类型都配了带故事正文的完整示例,包括feat(payments)(Apple Pay 支持)、fix(api)(分页偏移 off-by-one 错误)、refactor(user-service)(抽取共享校验工具)、perf(dashboard)(图表懒加载)、docs(readme)、test(auth)、chore(deps)(eslint 升级)、ci(GitHub Actions 缓存)、revert等。
Scope 指南:scope 可选但强烈推荐,应是标识代码库区域的短名词(auth、api、dashboard、payments),在项目内保持一致(不要混用user和users),当改动真正全局性时可省略。
正文写作技巧:写正文前自问三个问题——"这次改动前什么坏了/缺失了?"、"为什么选择这个方案而非其他?"、"对用户或开发者来说改动后有何不同?";同时避免复述 diff 已展示的内容(如"改了个变量名")、避免模糊语言("various improvements")以及避免将来时("this will fix...",应使用现在/过去时)。
提交信息反模式对照表:
| ❌ Bad | ✅ Better |
|---|---|
fix bug | fix(cart): prevent duplicate items on rapid add-to-cart clicks |
updates | feat(profile): allow users to update display name |
WIP | Don't commit WIP — stash it |
misc changes | Split into separate, meaningful commits |
John's changes | Describe what changed, not who changed it |
与仓库内其他提交类技能的协同
在 awesome-copilot 仓库中,围绕"提交信息"存在多个互补技能,理解分工有助于按场景选择:
- skills/gitmoji/SKILL.md:按 gitmoji 约定生成带 emoji 的提交信息,仅生成消息不执行 git 命令。其文档明确写道:如果项目遵循纯 Conventional Commits(
feat:、fix:...)而无 emoji,应使用conventional-commit或commit-message-storyteller技能;不确定时先让用户提供git log --oneline -10。 - skills/conventional-commit/SKILL.md:面向"一键执行提交"的场景,用结构化 XML 模板构造提交信息,并由 Copilot 直接在集成终端运行
git commit -m "type(scope): description"。 - skills/git-commit/SKILL.md:可执行
git commit的完整工作流技能,包含 diff 分析、智能暂存与 Git 安全协议(不更新 git config、不做破坏性操作、不跳过 hooks、不强制推送主干等)。
而commit-message-storyteller的独特价值在于叙事深度:它默认不执行 git 命令,产出可复制的消息 + 一行故事说明,专精于把 diff 背后的"为什么"讲清楚——是四者中最适合提升开源项目与团队提交历史可读性的选择。
如何安装与使用该技能
依据 docs/README.skills.md 的说明,该技能可通过 GitHub CLI 安装:
gh skills install github/awesome-copilot commit-message-storyteller(需 GitHub CLI v2.90.0 及以上版本);或将skills/commit-message-storyteller文件夹手动复制到本地技能目录。安装后在提示中引用技能名,或让 Agent 根据上述触发场景自动发现即可。
技能的结构本身也经受仓库工程化校验:eng/validate-skills.mjs会检查每个技能目录的SKILL.md存在性、frontmatter 中name/description的合法性、文件夹名与技能名一致,以及捆绑资源大小上限(5MB)。commit-message-storyteller的 frontmatter 与配套资源references/conventional-commits-guide.md正符合该校验标准,可直接作为自定义技能的编写范本。
实践要点速览
- 输入即素材:优先让用户粘贴
git diff --staged,模型自动提取"改了什么、为什么、谁触发的"。 - 类型先于措辞:先用上文的 10 类型判定表定基调,再动笔写句子。
- 主题行是一句话的承诺:祈使语气 + ≤72 字符 + 不带句号,如
perf(dashboard): lazy-load chart components。 - 正文只讲 why:diff 已经给出 what,正文聚焦"之前的问题 + 修复思路 + 备选方案"。
- 脚注承载可追溯性:
Closes #xxx关 issue,BREAKING CHANGE:标记破坏性变更。 - 宁可拆分不可杂糅:逻辑独立的变更拆成多条提交并告知用户。
- 尊重团队约定:项目若用 gitmoji 走 skills/gitmoji/SKILL.md,若需一键执行走 skills/conventional-commit/SKILL.md,讲故事则用本技能。
【免费下载链接】awesome-copilotCommunity-contributed instructions, agents, skills, and configurations to help you make the most of GitHub Copilot.项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-copilot
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考