关于 commit-changes
commit-changes 是一项用于撰写简洁、基于证据的 Git 提交说明并规范提交流程的技能。它指导开发者验证更改、检查差异、处理二进制文件审批,并在用户批准后提交;除非用户要求,否则不推送。
主要功能
- 01运行格式化和相关测试
- 02检查工作区与暂存区差异
- 03按更改规模调整说明
- 04提交前等待用户批准
- 05检查暂存文件中的二进制文件
- 06未经要求不推送
适用场景
- 01概述小修复或大型更改
- 02描述更改前确认检查结果
- 03提交前检查暂存文件
- 04获得批准后再提交
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ koruworks/ skills --skill commit-changes安装后在 Claude Code 中输入/commit-changes确认已加载。
详细介绍
提交摘要
提交消息会被阅读三次:下一位查看 git log 的人、编写变更日志的人,以及受托将一次发布改写成营销文案或用户指南章节的大模型。一次写好,满足这三方需求。
结构
- 描述之前先验证。 运行项目的格式化工具,以及与改动规模相称的测试,使用项目自身的命令。摘要会把测试状态陈述为事实,因此必须属实;明确列出未运行的检查。
- 阅读实际差异——运行
git status --short、git diff --stat,并查看本次会话中并非由你编写的内容对应的差异块。不要凭对话记忆来总结;工作树才是事实。趁此检查暂存内容中是否有二进制文件——参见 二进制文件需要批准。 - 根据差异规模控制篇幅(见下文 篇幅比例),然后按照结构起草摘要——只使用这次改动足以支撑的部分。
- 展示给用户,然后停止。 暂时不要提交。(无人值守运行的技能——例如 execute-plan——可以预先批准这一步;它会明确说明。)
- 获批后提交。绝不推送。 只有在同一轮请求中明确提出时才推送。
篇幅比例
消息的长度应与改动相称,而不是与模板相称。下面的每位读者都会为冗长内容付出代价:浏览 git log 的人得滚过这些内容,而变更日志大模型会照单全收,把一行修复夸大成一项功能公告。
- 小型修复——一个差异块、一个文件、一项可见效果——写一个主题行和一到三句话:说明哪里有问题、改了什么;如果差异无法直接说明原因,再补充为什么。不要加标题。
- 中型改动——多个文件、一个功能,或一个包含决策的错误修复——写开篇段落,再加上下面确有实质内容的部分。通常是决策和验证;途中发现的错误可以单独成段,没有错误则不加标题。
- 大型批次——许多文件、多个功能,或一次合并——使用完整结构。下方的模板就是为这种情况编写的。
每个部分都遵循同一规则:有事实可写时才保留,没有时就省略。标题下只有一句话,说明这次改动比模板所适用的规模更小。不要写“权衡:无”——直接省略即可。
读者不会改变篇幅,只会影响必须保留的内容:
git log需要主题行在任何规模下都能说明用户可感知的改动。- 变更日志 需要一句可以完整摘录的句子。对于小型修复,这就是正文的第一句话;即使修复只是列表中的一个错别字,也要用用户能理解的语言来写。
- 下一位工程师 需要知道差异没有说明的原因。两行修复若原因不明显,仍要说明原因;二十个文件的重构若原因显而易见,则不需要加一个假装有内容的决策部分。
验证是唯一绝不能因篇幅而省略的部分,只能缩短:小型修复用一个从句说明运行了什么、没有运行什么。
结构
大型批次的完整结构。较小的改动只保留主题行、开篇段落,以及有内容的部分——参见篇幅比例。
<subject: what a user can now do, or what changed for them — one line>
<opening: the problem it solves, in two or three sentences. What was wrong
before, and what the change is. This paragraph is the one a changelog or a
marketing blurb can lift whole, so write it in user terms, not module terms.>
<Themed sections with headings.> Group by what the reader cares about, not by
module or file. "The menu", "The tab strip", "Typography" beat
"src/menu" and "lib/render".
<Decisions worth keeping.> For each: what was chosen, what the alternative
was, and why it lost. A decision recorded without its alternative is an
assertion; with it, it is an argument the next person can re-open honestly.
<Bugs found along the way.> Especially pre-existing ones. Say plainly whether
a user would have felt it — that is what decides if it earns a changelog line.
<Trade-offs and costs.> What got worse, what a behaviour change costs someone
who relied on the old one.
<Closing: verification.> What was tested, what was confirmed by running the
app, and — separately and explicitly — **what was not**.
这些摘要为何有用
- 开头先说用户能感受到的变化,而不是促成它的重构。重构放在后面,解释怎么做,而不是做了什么。
- 说明原因,而不只是结果。
git diff已经能说明结果。推理是唯一无法从代码树中还原的部分。 - 说清被放弃的替代方案。“在第一个菜单旁边放置第二个菜单,而不是嵌套在其中,因为嵌套会让三个函数都必须处理层级”能告诉后来的人,为什么不该把它“简化”回去。
- 记录意外情况。 平台怪癖、行为与文档不符的 API、原来至关重要的常量。这些是别人无法重新推导出的内容。
- 用单独的句子标明未经验证的内容。 下游大模型会毫不犹豫地宣称功能已经上线。如果某项内容只经过单元测试,或者从未见过它实际运行,就要明确说明,不能让人轻易扫过。
- 每条写得简洁,不必刻意减少条数。 信息密集可以,凑字数不行。每一行都应包含读者无法猜到的事实——如果这次变更只有三个这样的事实,摘要就写三句话。
诚实原则
这些原则比平时更重要,因为摘要的影响会在下游放大。
- 绝不描述 diff 中不存在的行为。
- 绝不声称运行过并未执行的测试或手动检查。
- 如果变更受某个标志控制,说明是哪一个标志,以及它的默认值。
- 如果某项功能仅适用于特定平台,就要明确说明——在更新日志中承诺 Linux 用户可以使用仅适用于 Windows 的功能,会引来支持请求。
- 与其保持沉默,不如写“尚未进行视觉确认”。沉默会被理解为已确认。
二进制文件需要审批
未经用户事先同意,绝不提交二进制文件。 无论是视频、音频、压缩包、编译产物、字体,还是大图片。先询问,说明文件名和大小,然后等待回复。
原因在于 Git 历史是永久的。一个文件一旦提交,就会永远留在每个克隆仓库中,即使后续提交删除了它也一样——工作树看起来干净了,但 .git 仍要承担存储成本。要把它移除,就必须重写历史;在私有分支上这样做成本很低,但一旦合并并被拉取,就会造成干扰。事后无法悄无声息地撤销,所以这道关卡要放在提交之前,而不是之后。
每次提交前都要检查暂存区,而不是工作树——二进制文件在 numstat 的两列中都会显示为 -:
git diff --cached --numstat | awk '$1=="-" && $2=="-" {print $3}'
如果有任何输出,就停下来询问。说明每个文件是什么、大小是多少,以及为什么这项变更似乎需要它。通常,下面两种做法都比直接提交更好:
- 改为托管在其他地方。 媒体、示例录音和可下载内容应放在资源托管服务或对象存储中,仓库里只保留 URL、校验和(例如 SHA-256)以及获取文件的步骤。
- 改为生成文件。 如果构建步骤能够生成该文件,就提交构建步骤,并忽略生成的产物。
这是一道审批关卡,不是禁令——有些二进制文件确实应该放在代码树中,例如少量品牌素材。由用户决定哪些文件可以提交;关键在于,只要决定仍容易撤回,就应由用户来做决定。
提交
- 将文档纳入同一次提交。文档也是变更的一部分,因此如果项目会记录决策,提及某项决策的摘要旁边也应附上相应的决策记录。
- 修改现有提交还是新建提交需要自行判断,值得明确说明,而不是想当然:如果现有提交仍属于同一项工作,就修改它;如果这批变更是一个独立步骤,就新建提交。说明你的选择及原因,以便用户提出调整。
- 结尾添加你所在环境或项目要求的共同作者或签署信息——切勿照搬其他 Agent 会话中的信息。
- 通过文件或 heredoc 编写提交信息,绝不要串联使用多个
-m标志——上述结构无法通过这种方式保留。在 Windows PowerShell 中,优先将正文写入文件,然后使用git commit -F path。 - 不要推送。 无论是后续操作还是为了方便,都不要推送。
注意事项
- 未跟踪的杂项文件。 在执行
git add -A前用git status检查是否有多余文件;不要提交这些文件。路径排除 pathspec 可能会因文件名特殊而失效——暂存后、提交前再次运行git status验证。git add -A也可能意外纳入二进制文件:之后运行上文提到的 numstat 检查。 - 非预期的重新格式化。 如果开始时工作树并不干净,格式化工具可能会修改与本次变更无关的文件。应说明这一点,避免让人误以为这是有意为之。
- 过时的构建结果。 如果用户在你工作期间一直在测试,他们的截图可能早于当前描述的变更。若用户的反馈与代码不一致,最好用一句话说明。