背景
在使用 /commit skill 提交代码时,反复出现三类问题:漏网 commit、type 混用、body 为空。这篇笔记记录这三个现象的本质、涉及的 Git 机制,以及如何通过修改 skill 从根本上解决它们。
三个典型现象
现象 1:漏网 commit
清理日志后发现遗漏,分别开了两个新 commit,message 写着”漏网一条”。
- 表象:git log 多出打补丁式的 commit,历史显得零碎
- 本质:把”补漏”误当成”新目的”,违反了一个 commit = 一个完整意图的原则
现象 2:type 混用
一个 commit 用了 perf(video),但实际包含了清日志(chore)+ 性能优化(perf)+ 文档更新三件事。
- 表象:type 和实际改动内容对不上,读历史时产生误导
- 本质:type 是分类标签,混合目的时无法准确分类,只能选其一,其余被掩盖
现象 3:body 为空
docs 类 commit 没有写 body,只有 subject。
- 表象:只知道”更新了文档”,不知道为什么更新、更新了什么结论
- 本质:docs/chore/refactor 这类 commit,subject 天然只能描述操作,body 是传达”为什么”的唯一地方,缺失则信息丢失
涉及的 Git 机制
Conventional Commits 规范
格式:type(scope): subject + body
| 字段 | 说明 |
|---|---|
type | 改动类别:feat / fix / perf / chore / docs / refactor / test / style |
scope | 影响范围,单模块加,跨模块省略 |
subject | 描述效果而非操作,“修复卡顿”而非”删除日志” |
body | 说明 why,让人不看代码也能理解 |
判断 subject 是否合格
把 subject 给 3 个月后的自己看:能不能不看代码就理解这次 commit 的意义?如果不能,重写。
git commit —amend
把当前工作区的改动并入上一个 commit,不产生新 commit。
git add <files>
git commit --amend --no-edit # 保留原 message
git commit --amend # 同时修改 message适用场景:发现上一个 commit 有遗漏,立刻补上。
注意:会改写历史,已推送时需要 git push --force。
git rebase -i(交互式 rebase)
对一段历史 commit 批量重写,每行一个操作:
| 操作 | 含义 |
|---|---|
pick | 保留不变 |
reword | 保留改动,修改 message |
fixup | 并入上一个 commit,丢弃 message(等同于事后 amend) |
squash | 并入上一个 commit,保留 message |
非交互式自动化:通过环境变量注入脚本,绕过编辑器,实现完全脚本化:
GIT_SEQUENCE_EDITOR=/tmp/seq.sh \
GIT_EDITOR=/tmp/msg.sh \
git rebase -i <base-commit>GIT_SEQUENCE_EDITOR:控制 todo 文件(把 pick 改成 fixup/reword 等)GIT_EDITOR:控制每次 reword 时的 message 输入(按第一行内容识别当前 commit,替换为预准备的新 message)
这次实际用法示例(seq editor 脚本核心逻辑):
for line in lines:
if re.search(r'漏网关键词', line):
line = re.sub(r'^pick', 'fixup', line)
elif re.search(r'需要改message的关键词', line):
line = re.sub(r'^pick', 'reword', line)git push —force
rebase / amend 后本地和远程历史分叉,必须 force push 同步:
git push --force origin main协作仓库慎用
force push 会覆盖远程历史,在多人协作仓库中可能覆盖他人工作。个人仓库可以直接用。
/commit skill 的工作原理
/commit 是 Claude Code 的一个 skill(位于 ~/.claude/skills/commit/SKILL.md),通过 /commit 命令触发。
Skill 的本质:向 Claude 注入一段「工作流程 + 约束规则」的上下文,让 Claude 在执行任务时遵循特定步骤,而不是随意发挥。
原有流程(7 步):
- 状态检查
- 安全检查(敏感文件、冲突标记)
- 代码审查(遗留日志、TODO)
- 生成符合 Conventional Commits 的 message
- 用户确认
- 执行提交
- 询问推送
为什么会出问题 → 为什么这样修复有效
| 问题 | 根本原因 | 修复方案 | 为什么有效 |
|---|---|---|---|
| 漏网 commit | skill 没有 amend 路径,发现遗漏只能新开 commit | Step 1 检测今天的 commit → 主动询问是否补漏;Step 5 增加 amend 选项 | 把”是否 amend”变成流程中的显式判断点,而非靠执行者自发想到 |
| type 混用 | 自检是内部”过一遍”,没有强制执行 | 自检改为”逐条执行不能省略”,body 含 fix 类内容时强制标注 [fix] 或提示拆分 | 弱约束变成强制步骤,从”可能检查”变成”必须检查” |
| body 为空 | ”可选”太宽泛,没有区分何时必须写 | 明确规则:docs/refactor/chore 必须写 body | 给出明确判断标准,消除模糊地带 |
| subject 是操作描述 | 没有在生成后检查描述类型 | 自检第 1 条:含操作动词列举时重新生成 | 生成和检查分离,增加验证步骤 |
关键设计原则
规则不够,需要流程兜底。
光在 skill 里写”描述效果而非操作”是不够的——Claude 生成时仍然可能写出操作描述。真正有效的做法是:在流程中加入显式的验证步骤,生成之后再过一遍检查清单,不合格就重新生成。
这个原则适用于所有 skill 的设计:
- 约束条件 → 放进规则
- 规则的执行 → 靠流程中的强制检查点保障
- 用户决策 → 靠 AskUserQuestion 在关键节点收集确认