generate-commit

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Generate Commit

生成提交

Write a commit message for the changes the user staged, in this repo's conventional commit style, and commit after they approve it.
The index is the user's decision about what goes into this commit. Treat it as input, not something to rebuild. Everything below follows from that: inspect what is staged, check only that, and leave the rest of the working tree exactly as you found it.
针对用户暂存的更改,按照本仓库的 conventional commit 风格编写 commit message,并在用户批准后提交。
index 是用户对本次提交内容作出的决定。将其视为输入,而不是需要重新构建的东西。后续所有步骤都遵循这一点:只检查已暂存的内容,并将 working tree 的其余部分保持原样。

Step 1: Snapshot and inspect the index

第 1 步:记录并检查 index

bash
git status --short --untracked-files=all
git write-tree              # prints a tree hash: remember it as ORIG_TREE
git diff --cached --stat
git diff --cached
ORIG_TREE
records the index exactly as the user left it. On abort,
git read-tree <ORIG_TREE>
puts it back without touching working-tree files. Shell variables do not survive between tool calls, so keep the hash itself in your notes.
If something is staged, use that and only that. Do not run
git add -A
,
git add .
, or
git commit -a
. Unstaged edits and untracked files stay out of the commit, even when they look related. Mention them in one line ("README.md is modified but not staged; leaving it out") so the user can add them if they meant to.
If nothing is staged:
  • With a clean working tree, say there is nothing to commit and stop.
  • Otherwise list the modified and untracked files and ask whether to stage all of them, a subset, or none. Stage only after the user agrees, and stage the paths they chose (
    git add -- <paths>
    ). Do not fall back to
    git add -A
    silently.
bash
git status --short --untracked-files=all
git write-tree              # prints a tree hash: remember it as ORIG_TREE
git diff --cached --stat
git diff --cached
ORIG_TREE
会精确记录用户留下的 index 状态。中止时,
git read-tree <ORIG_TREE>
可在不触碰 working-tree 文件的情况下将其恢复。Shell 变量不会在不同 tool 调用之间保留,因此请在 notes 中保存 hash 本身。
如果存在已暂存内容,只使用这些内容。不要运行
git add -A
、
git add .
或
git commit -a
。即使未暂存的编辑和未跟踪文件看起来与本次改动相关,也必须将其排除在 commit 之外。用一行说明(“README.md 已修改但未暂存;将其排除在外”),以便用户在确有需要时自行添加。
如果没有任何已暂存内容:
  • 如果 working tree 干净,说明没有可提交的内容并停止。
  • 否则,列出已修改和未跟踪的文件,并询问用户要 stage 全部文件、一个子集,还是不 stage。只有在用户同意后才执行 stage,并且只 stage 用户选择的路径(
    git add -- <paths>
    )。不要在未说明的情况下退回到
    git add -A
    。

Step 2: Check for files that should not be committed

第 2 步:检查不应提交的文件

Before staging anything, and again over the staged file list, flag files that look like secrets or scratch work. Look at names, at the content of small untracked files, and at the diff (not the whole file) of modified tracked files, so a README that mentions
API_KEY
does not raise an alarm:
  • Names:
    .env*
    ,
    *.pem
    ,
    *.key
    ,
    id_rsa*
    ,
    *.p12
    ,
    credentials*
    ,
    secrets*
    ,
    *scratch*
    ,
    *notes*.txt
    ,
    *.log
    ,
    *.tmp
    ,
    *.bak
    ,
    .DS_Store
    , large binaries.
  • Contents (for example
    git diff --cached | grep -nEi '...'
    ):
    api[_-]?key
    ,
    token
    ,
    secret
    ,
    password
    ,
    BEGIN .*PRIVATE KEY
    ,
    sk-[A-Za-z0-9-]+
    ,
    AKIA[0-9A-Z]{16}
    ,
    ghp_[A-Za-z0-9]+
    ,
    xox[bp]-
    .
If a staged file matches, stop and ask before going on, and offer to unstage it (
git restore --staged -- <path>
). If an unstaged or untracked file matches, warn in one line and keep it out of the commit. A false positive costs one question; a committed key costs a rotation.
在 stage 任何内容之前,以及再次检查已暂存文件列表时,标记看起来像 secret 或临时文件的项。检查文件名、小型未跟踪文件的内容,以及已修改的受跟踪文件的 diff(而不是整个文件),这样 README 中提到
API_KEY
就不会引发警报:
  • 名称:
    .env*
    、
    *.pem
    、
    *.key
    、
    id_rsa*
    、
    *.p12
    、
    credentials*
    、
    secrets*
    、
    *scratch*
    、
    *notes*.txt
    、
    *.log
    、
    *.tmp
    、
    *.bak
    、
    .DS_Store
    、大型二进制文件。
  • 内容(例如
    git diff --cached | grep -nEi '...'
    ):
    api[_-]?key
    、
    token
    、
    secret
    、
    password
    、
    BEGIN .*PRIVATE KEY
    、
    sk-[A-Za-z0-9-]+
    、
    AKIA[0-9A-Z]{16}
    、
    ghp_[A-Za-z0-9]+
    、
    xox[bp]-
    。
如果已暂存文件匹配其中一项,停止并询问用户是否继续,同时提供取消暂存该文件的选项(
git restore --staged -- <path>
)。如果未暂存或未跟踪文件匹配其中一项,用一行警告并将其排除在 commit 之外。误报只会多问一次;提交密钥则意味着必须进行轮换。

Step 3: Run the project's lint on the staged files

第 3 步:对已暂存文件运行项目的 lint

The goal is to catch problems in this commit, not to clean up the repo.
  1. Find the command CI actually runs. Read
    .github/workflows/*.yml
    (or
    .gitlab-ci.yml
    ,
    .pre-commit-config.yaml
    , a
    Makefile
    /
    justfile
    lint
    or
    check
    target, or the
    scripts
    in
    package.json
    ). Use those commands with the project's runner (
    uv run
    ,
    npm run
    ,
    pnpm
    , and so on). Do not guess a formatter the project has not adopted. A repo that runs
    ruff check
    in CI has not opted into
    ruff format
    .
  2. Run it in check mode on the staged paths only:
    bash
    git diff --cached --name-only --diff-filter=ACMR -- '*.py' | xargs uvx ruff check
    That example uses CI's ruff; substitute the project's own command and globs. Piping through
    xargs
    avoids shell word-splitting differences (zsh does not split
    $FILES
    ). Filter that list to the file types the tool handles. When a tool cannot take a path list (for example
    go vet ./...
    ), limit it to the affected packages or directories. When no lint is configured, say so and continue. Do not invent one.
  3. On failure, report it and ask. Show the findings with file and line. Note any that sit on lines this diff did not touch, since those existed before. Then let the user choose: fix the staged files, commit anyway, or abort. Never reformat the whole repo, and never fix files outside the staged set.
  4. If the user asks you to fix, edit only the staged files, then re-stage those paths. If a file is partly staged (it shows in both
    git diff
    and
    git diff --cached
    ), re-staging also picks up its unstaged hunks. Say so and ask before you re-stage it.
Do not run the full test suite by default; it is slow and does not change the message. Run tests only when the user asks or the project's
CONTRIBUTING.md
requires them before every commit. Then run only the tests related to the staged files and report the results.
Do not write the lint command, or anything else, into
CLAUDE.md
,
AGENTS.md
, or any other tracked file. This skill changes nothing except the commit.
目标是发现本次提交中的问题,而不是清理整个仓库。
  1. 找出 CI 实际运行的命令。 阅读
    .github/workflows/*.yml
    (或
    .gitlab-ci.yml
    、
    .pre-commit-config.yaml
    、
    Makefile
    /
    justfile
    中的
    lint
    或
    check
    target,或者
    package.json
    中的
    scripts
    )。使用项目的 runner 执行这些命令(
    uv run
    、
    npm run
    、
    pnpm
    等)。不要猜测项目尚未采用的 formatter。一个在 CI 中运行
    ruff check
    的仓库,并不表示它已选择使用
    ruff format
    。
  2. 仅以 check mode 对已暂存路径运行它:
    bash
    git diff --cached --name-only --diff-filter=ACMR -- '*.py' | xargs uvx ruff check
    该示例使用 CI 中的 ruff;请替换为项目自己的命令和 glob。通过管道传给
    xargs
    可以避免 shell 的 word-splitting 差异(zsh 不会拆分
    $FILES
    )。将列表过滤为该 tool 能处理的文件类型。当某个 tool 无法接受路径列表时(例如
    go vet ./...
    ),应将其限制在受影响的 package 或 directory。如果项目未配置 lint,就说明这一点并继续。不要自行虚构一个命令。
  3. 失败时,报告问题并询问用户。 展示包含文件和行号的检查结果。指出位于本次 diff 未触及行上的问题,因为它们在改动前就已存在。然后让用户选择:修复已暂存文件、仍然提交,或中止。绝不要重新格式化整个仓库,也绝不要修复已暂存集合之外的文件。
  4. **如果用户要求修复,**只编辑已暂存文件,然后重新 stage 这些路径。如果某个文件只有一部分已暂存(它同时出现在
    git diff
    和
    git diff --cached
    中),重新 stage 也会把未暂存的 hunks 一并加入。务必说明这一点,并在重新 stage 之前征求同意。
默认不要运行完整 test suite;它速度慢,而且不会改变 commit message。仅当用户要求,或项目的
CONTRIBUTING.md
要求每次 commit 前运行测试时,才运行测试。然后只运行与已暂存文件相关的测试并报告结果。
不要将 lint 命令或任何其他内容写入
CLAUDE.md
、
AGENTS.md
或其他受跟踪文件。除本次 commit 之外,此 skill 不应进行任何更改。

Step 4: Learn the repo's conventions

第 4 步:学习仓库的约定

bash
git log --format=%s -30
Read the types and scopes this repo actually uses, for example
docs(adr):
,
ci:
,
test(fitness-config):
,
fix(fitness-config):
. Prefer them over any generic list. When the history is not conventional, use the standard types:
feat
,
fix
,
docs
,
style
,
refactor
,
perf
,
test
,
build
,
ci
,
chore
,
revert
. Skim
CONTRIBUTING.md
for commit rules if it exists. Rules there override this skill.
Scope: reuse a scope the log already uses for these files (check
git log --format=%s -- <path>
for a staged path). If none fits, use the most specific module or directory that covers every staged file, or leave the scope out. Never join several scopes into one, such as
ci,docs,scripts
.
bash
git log --format=%s -30
读取仓库实际使用的 type 和 scope,例如
docs(adr):
、
ci:
、
test(fitness-config):
、
fix(fitness-config):
。优先使用这些约定,而不是任何通用列表。如果历史记录不遵循 conventional commit,则使用标准 type:
feat
、
fix
、
docs
、
style
、
refactor
、
perf
、
test
、
build
、
ci
、
chore
、
revert
。如果存在
CONTRIBUTING.md
,快速浏览其中的 commit 规则。该文件中的规则优先于本 skill。
Scope: 对这些文件复用日志中已经使用的 scope(针对某个已暂存路径检查
git log --format=%s -- <path>
)。如果没有合适的 scope,就使用能够覆盖每个已暂存文件的最具体 module 或 directory,也可以省略 scope。绝不要把多个 scope 合并成一个,例如
ci,docs,scripts
。

Step 5: Check whether the diff is one change

第 5 步:检查 diff 是否只包含一项改动

When the staged files serve unrelated purposes (for example a CI timeout, a docs fix, and a new script feature), say so before writing the message. Propose a split: one commit per concern, with the files for each and a draft subject for each. Then ask whether to:
  • Split. Unstage everything (
    git restore --staged -- .
    ). For each group, stage that group's paths, confirm the message, and commit. When done, the index holds nothing the user had not staged. If a single file mixes concerns, say so; splitting it needs
    git add -p
    , which the user has to do themselves.
  • Commit together. Write one message whose body lists every concern.
A change and its own tests, docs, or config are one concern, so do not suggest splitting those.
当已暂存文件服务于互不相关的目的时,例如 CI timeout、文档修复和新的 script 功能,应在编写 message 前说明这一点。提出拆分方案:每个 concern 一个 commit,并列出每组文件以及每个 commit 的 subject 草案。然后询问用户是否:
  • 拆分。 取消暂存全部内容(
    git restore --staged -- .
    )。对每一组,stage 该组的路径,确认 message,然后 commit。完成后,index 中不应包含用户未曾暂存过的任何内容。如果单个文件混有多个 concern,说明这一点;拆分该文件需要
    git add -p
    ,必须由用户自行完成。
  • 一起提交。 编写一条 message,其 body 列出每个 concern。
某项改动及其配套的 tests、docs 或 config 属于同一个 concern,因此不要建议拆分它们。

Step 6: Write the message

第 6 步:编写 message

text
type(scope): imperative summary of the change

Optional body: what changed and why, wrapped at 72 columns.
Use bullets when there are several distinct points.
  • Start the subject with an imperative verb ("add", "fix", "accept"), not "added" or "fixes". Keep it at 72 characters or fewer, and do not end it with a period.
  • Add a body when the subject cannot say why the change was made, when it covers more than one point, or when the change is breaking. Leave it out for small, self-explanatory changes.
  • Mark breaking changes with
    !
    after the type or scope and a
    BREAKING CHANGE:
    footer.
  • Do not add
    Co-Authored-By
    , "Generated with", or any model or tool name. It adds noise to the history. If the user's own instructions require a trailer, follow them.
text
type(scope): imperative summary of the change

Optional body: what changed and why, wrapped at 72 columns.
Use bullets when there are several distinct points.
  • subject 以祈使动词开头(“add”、“fix”、“accept”),而不是 “added” 或 “fixes”。将其控制在 72 个字符以内,且末尾不要加句号。
  • 当 subject 无法说明为何进行改动、涵盖多个要点或属于 breaking change 时,添加 body。对于规模较小且不言自明的改动,可以省略 body。
  • 在 type 或 scope 后添加
    !
    来标记 breaking change,并添加
    BREAKING CHANGE:
    footer。
  • 不要添加
    Co-Authored-By
    、“Generated with” 或任何模型或 tool 名称。这会给历史记录带来噪声。如果用户自己的指令要求某个 trailer,则遵循该指令。

Step 7: Present for review

第 7 步:提交审阅

Show the full message, the list of files it will commit, and any warnings from Steps 1-3. Then ask with AskUserQuestion:
  1. Use as-is: commit with this message.
  2. Edit: take the user's revised message and commit with it.
  3. Abort: no commit, and the index is restored.
展示完整 message、将要提交的文件列表,以及第 1 至第 3 步中的任何 warnings。然后使用 AskUserQuestion 询问:
  1. 原样使用:使用这条 message 提交。
  2. 编辑:采用用户修改后的 message 并提交。
  3. 中止:不提交,并恢复 index。

Step 8: Commit or abort

第 8 步:提交或中止

Commit with a HEREDOC so the body and line breaks survive:
bash
git commit -F - <<'EOF'
type(scope): subject

Body.
EOF
  • Let hooks run. Never pass
    --no-verify
    . If a pre-commit hook fails or rewrites files, show its output and go back to Step 3. Do not retry blindly.
  • After committing, run
    git status --short
    and confirm that the files the user left unstaged or untracked are still there and still uncommitted.
  • On abort: run
    git read-tree <ORIG_TREE>
    to put the index back exactly as the user left it, including anything they had staged. Do not use
    git reset HEAD
    , which also unstages their own staging. Undo any lint fixes you made only if the user asks. Then print "Aborted: no commit created; staging restored."
使用 HEREDOC 提交,以保留 body 和换行:
bash
git commit -F - <<'EOF'
type(scope): subject

Body.
EOF
  • 让 hooks 正常运行。绝不要传入
    --no-verify
    。如果 pre-commit hook 失败或重写了文件,显示其输出并返回第 3 步。不要盲目重试。
  • 提交后,运行
    git status --short
    ,并确认用户留下为未暂存或未跟踪的文件仍然存在,且仍未提交。
  • 中止时: 运行
    git read-tree <ORIG_TREE>
    ,将 index 恢复为用户离开时的确切状态,包括用户已经暂存的任何内容。不要使用
    git reset HEAD
    ,因为它也会取消用户自己的暂存。只有在用户要求时才撤销你做出的 lint 修复。然后输出“已中止:未创建提交;暂存状态已恢复。”

Constraints

约束

  • Never commit without explicit confirmation.
  • Never stage files the user did not stage or approve.
  • Never edit files outside the staged set, and never edit
    CLAUDE.md
    or other agent notes as a side effect.
  • Never push.
  • 未获明确确认,绝不提交。
  • 绝不 stage 用户未 stage 或未批准的文件。
  • 绝不编辑已暂存集合之外的文件,也绝不因副作用而编辑
    CLAUDE.md
    或其他 agent notes。
  • 绝不 push。