commitkit
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesecommitkit
commitkit
Turn the current changes into one or more clean commits with Conventional Commits messages inferred from the diff itself, not from a guess. The message describes what actually changed, in the imperative mood, with a correct type and scope. In a coding session the default is multiple commits, one per feature group or logically related change, never a single catch-all commit.
根据代码差异而非猜测,将当前更改转换为一个或多个符合Conventional Commits规范的清晰提交。提交信息采用祈使语气,包含正确的类型和范围,准确描述实际更改内容。在编码会话中,默认生成多个提交,每个提交对应一个功能组或逻辑相关的更改,绝不使用单一的笼统提交。
When this fires
触发场景
The user asks to commit ("commit this", "make a commit", "/commitkit", "commit my changes"). If they only want a message drafted (not committed), do everything except the final .
git commitThis skill is built for AI coding sessions where the user hands off with a bare "commit". In that mode you are expected to work autonomously: stage the right files yourself, group the work into as many commits as it deserves, commit them, and report back a table of what you created, without stopping to ask at each step.
当用户要求提交(如“提交这个”“创建提交”“/commitkit”“提交我的更改”)时触发。如果用户仅需要草拟提交信息(而非实际提交),则执行除最终外的所有步骤。
git commit本工具专为AI编码会话设计,适用于用户仅简单说“提交”的场景。在此模式下,你需要自主操作:自行暂存正确的文件,将工作内容分组为合适数量的提交,完成提交后,返回创建的提交列表,无需在每一步都询问用户。
Procedure
操作流程
1. Read the state
1. 读取状态
Start from the file-level shape of the change, never the full diff, in a single call:
sh
git status --short && git diff --stat HEAD # tree state + one line per file, one callBatch every git call in this skill the same way. This skill fires at the end of a session, when the context window is at its largest, and each extra Bash call re-pays that whole window as input. Chain commands with whenever no decision sits between them; spend a separate call only where you must stop and think between two commands.
&&Then decide how much diff you actually need, by asking who wrote these changes.
- You did, in this same context (the typical coding-session hand-off). You already know what the change does and, more importantly, why, and the why is the part a diff can't tell you: the approach you rejected, the test that caught a bug mid-way, the file you deliberately left alone. Group from the stat and write the body from what you know. Read a diff only for files you didn't touch yourself, or where you genuinely can't recall what landed.
- You didn't. You were dispatched as a subagent, the session is fresh, the changes are the user's own edits, or the work happened far enough back that it's no longer in context. Then the diff is your only source, but take it group by group, never wholesale. Sketch the groups from the stat first, then read each group's diff with and stop once that group's type, scope, and effect are clear. A pathless
git diff HEAD -- <paths>pulls the whole session's changes into context at once; the per-group read caps each read at the group you're actually writing about.git diff HEAD
When in doubt, read. A vague commit message costs more than the tokens it saved. But re-reading code you wrote minutes ago buys nothing: the stat already tells you which files moved, and you already know what you did to them.
Never read the content of generated files in either mode, meaning lockfiles (, , , ), build output, vendored directories, snapshots, compiled assets. Their stat line carries every bit of signal a commit message can use, and their diffs are the largest in most repos.
*.lockpackage-lock.jsonpnpm-lock.yamlgo.sum- When the user has delegated committing (the typical coding-session "commit" / "commit my changes"), you are free to stage the files you need yourself, so the paths for each logical group as you commit it. You don't have to ask first; grouping and staging is your job here.
git add - Only pause to ask when intent is genuinely ambiguous, e.g. the tree holds half-finished work, secrets, changes you suspect the user didn't mean to commit, or a file is partially staged and staging its whole path would include deliberately unstaged hunks. Never blindly across unrelated concerns; stage per group instead (see Group the work into multiple commits).
git add -A - If the user asked only for a message or a single specific commit, respect that and don't auto-split.
- If nothing has changed at all, stop and say so.
从文件级别的更改形态入手,而非完整差异,通过一次调用获取:
sh
git status --short && git diff --stat HEAD # 树状状态 + 每个文件一行信息,一次调用完成本工具中所有git调用均采用批量方式。 本工具在会话结束时触发,此时上下文窗口已达最大,每一次额外的Bash调用都会占用整个上下文窗口作为输入。只要两个命令之间无需决策,就用连接;仅当必须在两个命令之间思考时,才分开调用。
&&然后根据更改的作者,决定实际需要读取多少差异内容。
- 你在本次上下文中完成的更改(典型的编码会话交接场景):你已经知道更改的内容,更重要的是知道更改的原因——而这是差异无法告诉你的:你放弃的方案、中途发现bug的测试、你故意保留不动的文件。根据stat信息分组,结合你所知的内容撰写提交正文。仅在你未修改的文件,或确实无法回忆起更改内容时,才读取差异。
- 你未参与的更改:你作为子Agent被调用,会话刚启动,更改是用户自行编辑的,或者工作内容发生在太久之前已不在上下文中。此时差异是你唯一的信息来源,但要逐组读取,而非一次性读取全部。先根据stat信息草拟分组,然后用读取每组的差异,一旦明确该组的类型、范围和影响就停止读取。不带路径的
git diff HEAD -- <paths>会将整个会话的更改一次性拉入上下文;而逐组读取可以将每次读取的内容限制在当前处理的组内。git diff HEAD
如有疑问,就读取差异。模糊的提交信息比节省的token代价更高。但重新读取你几分钟前编写的代码毫无意义:stat信息已经告诉你哪些文件被修改,你也清楚自己做了什么。
无论哪种模式,都不要读取生成文件的内容,包括锁文件(、、、)、构建输出、依赖目录、快照、编译资源。它们的stat行已经包含了提交信息所需的全部信号,而它们的差异在大多数仓库中都是最大的。
*.lockpackage-lock.jsonpnpm-lock.yamlgo.sum- 当用户委托提交(典型的编码会话中的“提交”/“提交我的更改”)时,你可以自行暂存所需文件,因此在提交每个逻辑组时,使用添加对应路径。无需事先询问;分组和暂存是你的职责。
git add - 仅当意图确实不明确时才暂停询问,例如:工作区包含未完成的工作、敏感信息、你怀疑用户无意提交的更改,或者文件部分暂存,暂存整个路径会包含用户故意未暂存的代码块。切勿盲目使用暂存无关的更改;应按组暂存(参见将工作内容分组为多个提交)。
git add -A - 如果用户仅要求草拟信息或创建单个特定提交,请尊重用户需求,不要自动拆分。
- 如果没有任何更改,请停止操作并告知用户。
2. Decide type and scope from the diff
2. 根据差异确定类型和范围
Pick the from what the diff does, not what files it touches:
type| type | when |
|---|---|
| a new capability the user can see |
| a bug fix |
| documentation only |
| behavior-preserving code change |
| a performance improvement |
| adding or fixing tests |
| build system, deps, or pipeline |
| formatting/whitespace, no logic |
| routine maintenance that fits nothing above |
Scope is mandatory here. Unlike vanilla Conventional Commits, never omit it. Work out the module or feature group the diff belongs to (a package, module, directory, or feature area) and use that as the scope: . When a change is genuinely global or fits no single area (repo-wide config, tooling, cross-cutting cleanup), use as the scope: . Add a (or a footer) when the change breaks existing behavior.
feat(auth): …repochore(repo): …!BREAKING CHANGE:根据差异的实际作用而非涉及的文件选择:
type| type | 适用场景 |
|---|---|
| 用户可见的新功能 |
| 修复bug |
| 仅修改文档 |
| 不改变行为的代码调整 |
| 性能优化 |
| 添加或修复测试 |
| 构建系统、依赖或流水线相关更改 |
| 格式/空白调整,不涉及逻辑 |
| 符合上述任何类型的日常维护工作 |
Scope是必填项。与标准Conventional Commits不同,此处绝不能省略。确定差异所属的模块或功能组(包、模块、目录或功能区域)并将其作为scope:。当更改确实是全局的或不属于任何单个区域(仓库级配置、工具、跨领域清理)时,使用作为scope:。当更改破坏现有行为时,添加(或脚注)。
feat(auth): …repochore(repo): …!BREAKING CHANGE:3. Write the message
3. 撰写提交信息
Format:
type(scope): short imperative summary
one-line summary of why the change was made
- reason/change bullet
- reason/change bullet
Reference issues in a footer.The is required, so every message carries one, falling back to for global work.
(scope)(repo)Rules:
- Imperative mood, all lowercase subject. Never capitalize the first word or any word in the title (proper nouns and acronyms are the only exceptions), use no trailing period, and aim for ≤ 50 characters.
- The summary states the effect of the change ("add retry to fetch client"), not the activity ("changes to fetch client").
- A body is required. Open with a short one-line summary of why, then a bullet list capturing the reasons and the concrete changes. Keep it to what a reviewer needs. Don't pad trivial commits, but always include the summary line and at least one bullet.
- Do not add or tool advertising unless the user asked for it.
Co-authored-by
格式:
type(scope): 简短祈使语气摘要
更改原因的单行总结
- 原因/更改要点
- 原因/更改要点
在脚注中引用相关问题。(scope)(repo)规则:
- 主题使用祈使语气、全小写(专有名词和缩写除外),首单词不大写,标题末尾不加句号,长度尽量≤50字符。
- 摘要说明更改的效果(如“为fetch客户端添加重试机制”),而非操作本身(如“修改fetch客户端”)。
- 必须包含正文。开头用单行简短说明更改原因,然后用项目符号列表列出原因和具体更改内容。仅保留评审人员需要的信息。无需为琐碎提交添加冗余内容,但必须包含摘要行和至少一个项目符号。
- 除非用户要求,否则不要添加或工具推广信息。
Co-authored-by
4. Group the work into multiple commits
4. 将工作内容分组为多个提交
Before committing anything, map the changes to logical groups. Each feature group or related unit of work (a feature and its tests, a bugfix, a docs update, a refactor, a config bump) becomes its own commit. This is the default, not an exception: a session that touched three concerns should produce three commits, each with its own scope.
Group by what the change accomplishes, not by file type or directory. Keep a feature together with the tests and docs that belong to it rather than splitting them across commits. Don't over-fragment either; a single cohesive change is one commit even if it spans several files.
Order the groups so dependencies land first (e.g. a shared helper before the feature that uses it). When a file contains hunks from multiple groups, plan to stage it interactively rather than assigning the whole path to one group.
在提交任何内容之前,将更改映射到逻辑组。每个功能组或相关工作单元(功能及其测试、bug修复、文档更新、重构、配置升级)都成为独立的提交。这是默认行为,而非例外:涉及三个关注点的会话应生成三个提交,每个提交有自己的scope。
按更改的目的分组,而非文件类型或目录。将功能及其相关测试和文档放在同一个提交中,而非拆分到多个提交。也不要过度拆分:一个连贯的更改即使涉及多个文件,也应作为一个提交。
按依赖顺序排列分组(例如,先提交共享工具类,再提交使用该工具类的功能)。当一个文件包含多个组的代码块时,计划交互式暂存,而非将整个路径分配给一个组。
5. Commit each group
5. 提交每个分组
With every group and message already planned, stage and commit them all in one Bash call, chained with , and close the chain with the the hand-off needs:
&&git status -sbsh
git add <group 1 paths> && git commit -m "type(scope): summary" -m "why in one line
- reason/change bullet
- reason/change bullet" && \
git add <group 2 paths> && git commit -m "type(scope): summary" -m "why in one line
- reason/change bullet" && \
git status -sbInteractive staging of a mixed file (see Group the work into multiple commits) is the one step that can't join the chain. Commit up to that group in one call, handle the split, then chain the rest.
When the user delegated the commit ("commit", "commit my changes"), just do this for every group, with no per-commit confirmation. Only show messages for approval first if the user asked you to draft rather than commit. If a commit fails (e.g. a pre-commit hook rejects it), the chain stops at the failing group and later groups stay uncommitted, so surface the hook output, fix or ask, then resume the chain from that group. Don't retry blindly or bypass hooks with unless told to.
&&--no-verify在规划好所有分组和提交信息后,通过一次Bash调用完成所有暂存和提交操作,用连接,并在链末尾添加会话交接所需的:
&&git status -sbsh
git add <group 1 paths> && git commit -m "type(scope): summary" -m "why in one line
- reason/change bullet
- reason/change bullet" && \
git add <group 2 paths> && git commit -m "type(scope): summary" -m "why in one line
- reason/change bullet" && \
git status -sb混合文件的交互式暂存(参见将工作内容分组为多个提交)是唯一无法加入链式调用的步骤。先提交到该分组前的所有内容,处理拆分,然后继续链式调用剩余部分。
当用户委托提交(“提交”“提交我的更改”)时,直接对每个分组执行此操作,无需每次提交都确认。仅当用户要求草拟而非提交时,才先展示信息等待批准。如果提交失败(例如,预提交钩子拒绝),链会在失败的分组处停止,后续分组保持未提交状态,此时应展示钩子输出,修复问题或询问用户,然后从该分组继续链式调用。除非用户要求,否则不要盲目重试或使用绕过钩子。
&&--no-verify6. Hand off
6. 交接
Write this section in the procedural register: one instruction per sentence, active voice, present tense, no metaphor.
Close with what changed, where it landed, and the next move.
What changed. Print a summary table of the commits you created so the user sees the result at a glance:
| # | commit message | files |
|---|---|---|
| 1 | | |
| 2 | | |
List each commit's changed/created files in the last column. You already know them, since they're the paths you passed to for each group, so build the table from that rather than querying git again. If you do need to check, one covers every commit you just made; don't run a separate per commit. If a commit touches many files, list the key ones and add "+N more". If anything remains uncommitted (intentionally skipped or left for the user), note it under the table.
git addgit log --stat --oneline -<n>git showWhere it landed. Report the branch the commits sit on, and whether it has an upstream. The at the end of the commit chain already printed both in one line; report from that output rather than running it again. Commits on a local-only branch exist nowhere but this machine, and saying so is the most useful line in the report.
git status -sbNext. Name one move and stop. The work is committed but unpublished, so the default is to publish it: prkit when it's installed, to open a pull request from exactly these commits; otherwise and open the PR by hand. If the feature clearly isn't finished, say that instead and name the plain action, which is to keep building, then re-run commitkit for the next group. Don't push or open anything yourself; commitkit's job ends at the commit.
git push -u origin HEAD本部分采用流程化表述:每句一个指令,主动语态,现在时,无比喻。
以更改内容、提交位置和下一步操作结束。
更改内容:打印你创建的提交摘要表,让用户一目了然看到结果:
| # | 提交信息 | 文件 |
|---|---|---|
| 1 | | |
| 2 | | |
在最后一列列出每个提交修改/创建的文件。你已经知道这些文件,因为它们是你为每个分组传递给的路径,因此直接据此构建表格,无需再次查询git。如果确实需要检查,一次即可覆盖你刚创建的所有提交;不要为每个提交单独运行。如果一个提交涉及多个文件,列出关键文件并添加“+N个更多”。如果有任何内容未提交(故意跳过或留给用户),在表格下方注明。
git addgit log --stat --oneline -<n>git show提交位置:报告提交所在的分支,以及是否有上游分支。提交链末尾的已经在一行中打印了这两个信息;直接据此报告,无需再次运行该命令。仅存在于本地分支的提交仅保存在当前机器上,说明这一点是报告中最有用的信息。
git status -sb下一步操作:给出一个操作建议即可。工作内容已提交但未发布,默认建议发布:如果安装了prkit,则使用它基于这些提交创建拉取请求;否则使用并手动创建PR。如果功能明显未完成,则说明这一点并给出明确操作,即继续开发,之后为下一组更改重新运行commitkit。不要自行推送或创建任何内容;commitkit的职责在提交完成后结束。
git push -u origin HEADNotes
注意事项
- Never run ,
git push, or history-rewriting commands unless the user explicitly asks.git commit --amend - If a repo has its own commit convention (a , a commit template, or an obviously different style in
CONTRIBUTING.md), follow that over these defaults and say you did.git log - No filesystem or shell? Then you can't run . Instead read the diff the user provides and print the finished commit message as a codeblock for them to run themselves.
git
- 除非用户明确要求,否则绝不运行、
git push或重写历史的命令。git commit --amend - 如果仓库有自己的提交规范(、提交模板或
CONTRIBUTING.md中明显不同的风格),则遵循该规范而非本默认规则,并告知用户你已这么做。git log - 没有文件系统或Shell?则无法运行git。此时读取用户提供的差异,将最终的提交信息作为代码块打印出来,供用户自行运行。