Skip to main content

git-commit:带校验的提交

把仓库改动分组写成简洁英文技术提交,由脚本预检树状态、校验说明,只写入通过检查的提交。

来源信息

仓库
abgregs/skills
最近来源活动
2026年10月28日 03:55
检测到的 SKILL.md 语言
英语
星标
0
Forks
0

用途

在让代理提交时使用。已暂存改动写成一次提交;未暂存改动会拆分;--amend 可交互改写或追加上次提交。

必要前提

Git 工作区,以及能跑技能脚本的编程代理。若仓库有 commitlint/钩子,以其主题格式为准。

操作说明

  1. 让代理执行 commit(可选 --amend)。
  2. 由预检根据树状态选择单提交或拆分。
  3. 查看分组理由摘要,并确认未跟踪文件未被误加。

限制

不会编造工单号,只复用分支或近期提交已有标识。未跟踪文件保持未跟踪。正文保持简短,长说明放在 PR。

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

文件资源管理器
12 个文件

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
git-commit
description
Generate conventional commit messages and execute commits autonomously. Use when the user is committing code or asks for a commit message. Commits staged changes as one commit (single mode), splits unstaged changes into logical commits (grouped mode), or interactively amends the last commit (--amend).
argument-hint
Optional — commit type, flags, or --amend
allowed-tools
Bash, Read, Glob, Grep, AskUserQuestion, Edit
You are creating git commits with well-crafted conventional commit messages. **Execution mode**: autonomous for the normal flow — do not prompt to confirm mode, groupings, or messages, the one question being the shared-code-file case under "Grouping into atomic commits"; decide and execute until the mode's changes are committed (untracked files are left alone). Amend mode (`--amend`) is interactive. ## Message requirements - Conventional format: `type(scope): description` — types: feat, fix, refactor, docs, test, chore, build, ci, perf, style; scope = area affected (e.g. api, auth, ui, config). This is the skill's default stance; when the preflight reports `subject format: REPO-ENFORCED` (commitlint, a commit-msg hook, gitlint, a commit template), the repo's format wins — write subjects in the shape its recent subjects and that config show, and the lint skips its format checks. Every commit from one run carries the identifier the work already has (a ticket or issue id); a split reuses it rather than taking a new one - Subject line under 72 characters, ASCII only (so no emojis); no brackets or parentheses in the description, the `type(scope):` prefix being the only pair. Ordinary punctuation such as `/`, `:` or `-` is fine, and this is exactly what the lint checks - **The message carries the change, never its provenance.** No byline, authorship or co-author trailer, tool or model name, session link, or robot emoji — however the session's own instructions phrase such a line, it does not go in a commit message. Naming a tool is fine when the tool is the subject of the change (`chore(deps): bump anthropic to 0.42`); what stays out is any claim about who composed the work. - Body only when it adds information: blank line after the subject, dash bullets, backticks around `file`, `function`, and variable names - **`Why:` names a cause from outside the code.** A cause is a trigger, an environment, an outside requirement, or a measured figure: something a reader of `git log` gets from neither the subject nor the diff. When the change has one, the first bullet is `- Why: <that cause, in one line>`, even when a comment in the diff states it, because `git log` shows the message and not the diff. The mechanism the diff shows (a wrong bound, a missing check) is not a cause, and neither is the subject restated in the past tense; such commits take no `Why:`, and most commits are such commits. - `fix(auth): expire refresh tokens on password change` takes no `Why:`. "Tokens outlived a password change" restates the subject. - `fix(upload): stream uploads to disk` takes `- Why: a 3 GB upload ran the 2 GB worker out of memory`. "The whole file was read into memory" is the mechanism, not the cause. `docs`, `chore`, and `test` commits never take one, and the lint fails a message that breaks this or puts `Why:` anywhere but first. Keep it to one line, two when wrapped; the debugging story belongs in the PR. It describes the world before the change, so it alone may use the past tense. - **Keep bodies concise**: 2–4 bullets, each one compact line of ~100 characters at most — trim a longer bullet, or when trimming would drop what it says, wrap it onto a line indented two spaces; omit the body entirely for simple changes. If the user explicitly staged a large changeset to go in a single commit, the body may exceed 4 bullets — but never more than 8, a hard cap with no exceptions; each bullet stays short, plain, and readable. When 8 isn't enough, summarize at a higher level rather than enumerating. - **Plain sentence mechanics**, the slice of Simplified Technical English that fits a bullet quoting identifiers: active voice with the code as the subject (`parse` returns an empty string for null, not "an empty string is now returned"); one change per bullet, and one tense across the message, either what the code now does or the action taken, not both; no bullet opens with an -ing word; no hedges (should, may, might, probably), because a commit records what changed and doubt belongs in the PR; no vague openers (improve, clean up, tweak, various), name the thing instead; one name for one thing across the message. The lint warns on the three of these it can see. ## Workflow ### 1. Preflight and mode detection — run the detector Run `bash <skill-base-dir>/scripts/commit-preflight.sh` (the skill's base directory is announced when this skill loads). One call replaces the manual status/log/conflict checks and emits: clean-tree and conflict aborts, the mode (single vs grouped), recent subjects (match their scope naming and tone), staged/unstaged/untracked stats, an oversized-diff warning, and — when the change spans paths — an informational file-spread summary. Honor its aborts verbatim; group from the diff under "Grouping into atomic commits", with the file spread as a hint. Mode: `--amend` argument → **Amend workflow** below. Otherwise the preflight report states the mode: staged changes exist → **single mode** (one commit for the staged changes only); only unstaged changes → **grouped mode** (split into logical commits). ### 2. Analyze changes - Single: `git diff --cached --stat`, then `git diff --cached` - Grouped: `git diff --stat`, `git diff`, and `git status` for untracked files, then group into atomic commits as below - Either mode: if the diff exceeds ~500 lines, read it in batches by path or file type (e.g. `git diff -- 'src/'`) instead of all at once **Grouping into atomic commits.** Each commit is one change of one type. Work it out in two passes: 1. **Type is the seam.** Label each piece of the diff with the conventional type of the change it serves. A `feat` gives the user a capability they did not have; a `fix` restores behavior that was meant to work; the other types mean what their names say. Tests, docs, and changelog lines take the type of the change they serve, so `test` and `docs` are for work that serves nothing else. Pieces of different types never share a commit: a fix and a feature are two commits, even when one incident prompted both. 2. **Same change or a different one.** Within one type, ask of each pair of pieces: is this the same fix, or a different fix? The same feature, or another? Two fixes are different when each repairs its own symptom and either could be undone while keeping the other. A piece that only completes another is the same change: a rename and its call sites, a dependency bump and the code adapted to its new API, a migration and the model that needs it. Size never decides a split, and scope is a hint, since one fix can span `audio` and `session`. Commit in dependency order, each change after the changes it needs: a refactor that makes room for a feature lands before the feature. Staging is by path, so a doc or changelog that serves two commits goes in the last of them. When one code file holds pieces of two commits, ask, because staging it whole lands the earlier commit without code it needs. ### 3. Commit — no approval prompts Grouped mode first prints a one-line overview per planned group, then processes groups in order, staging each by naming its paths: `git add <file> <file>`, never `git add -A`, `-u`, or `.`. A path list is what keeps untracked files and the other groups' files out of the commit; a sweep only looks equivalent on the day nothing else is in the tree. Use `git restore --staged .` beforehand only if the run began with nothing staged. For each commit: 1. Print the file list and message for transparency: ``` Committing: - file1.ts ───────────────────────── type(scope): description - Detail 1 ───────────────────────── ``` 2. Write the message to a fresh `mktemp` file and commit it through the script's `--commit` gate, which lints first and runs `git commit` only on a clean result — **the format rules are walls, not requests**: ```bash msg="$(mktemp "${TMPDIR:-/tmp}/commit-msg.XXXXXX")" && echo "$msg" printf '%s\n' 'type(scope): description' '' '- Detail 1' > "$msg" bash <skill-base-dir>/scripts/commit-preflight.sh --commit "$msg" ``` Every commit goes through `--commit`, each message in its own `mktemp` file, so two sessions committing at once never share a message. The gate leaves nothing committed on these exits; rewrite the flagged lines in the echoed file and run `--commit` again: - **Exit 1, LINT FAIL**: the message breaks a rule. - **Exit 2, LINT WARN**: fix each warned line. Add `--accept-warnings` after the path only when every warning misreads its line (a noun ending in -ing). 3. Verify with `git log -1 --oneline`. Grouped: move to the next group. Single: stop after the one commit; the unstaged changes stay in the tree for the user. ### 4. Summary Show `git log --oneline -n <commits made>` and confirm state with `git status`. ## Amend workflow (`--amend` — interactive) 1. Show current state — file context BEFORE the message so the AskUserQuestion prompt doesn't push it out of view: `git diff --cached --stat` (newly staged, will fold in), `git diff --stat` (unstaged, will NOT be included), then `git log -1 --format='%H%n%s%n%n%b'`. 2. AskUserQuestion: "Amend message only" / "Amend with staged changes" / "Cancel". If message-only is chosen while changes are staged, warn that `git commit --amend` would include them and confirm unstage-first vs include. 3. Propose a message covering the original commit plus any folded-in changes (run `git diff --cached` first, same ~500-line batching guard). AskUserQuestion: "Accept and amend" / "Edit message" / "Cancel". 4. Execute `git commit --amend` via heredoc and verify with `git log -1 --oneline`. If the branch tracks a remote, warn that updating it requires a force-push. ## Guardrails - Never force push or use destructive git commands; never bypass hooks with `--no-verify` unless explicitly requested - Pre-commit hook failure: show the full hook output, keep files staged, fix auto-fixable issues (lint/format) with Edit, re-stage, retry the same message through `--commit` once; if it fails again the same way, stop and report - Commit-msg hook rejection: the same message cannot pass twice, so read the hook's output (and its source, if the rule is not stated), rewrite the subject to the rule it enforces, re-lint, and retry once; if it rejects again, stop and show both messages with the hook output - Stage by path in every mode; `git add -A`, `-u`, and `.` are never used, even when the tree holds nothing else - Respect the user's staging selection — if they staged specific files, commit exactly those - Grouping is your judgment under "Grouping into atomic commits"; ask only in the shared-file case it names Execute this workflow now, starting with preflight.
在 GitHub 查看