commit
GitHub将工作区变更转化为符合 Conventional Commits 规范的原子化提交。通过对比合并基精准过滤属于当前分支的文件,防止误提交其他分支的无关文件。支持独立使用或嵌入发布流程,仅负责暂存与提交,不涉及推送或 PR 操作。
触发场景
安装
npx skills add NeverSight/learn-skills.dev --skill commit -g -y
SKILL.md
Frontmatter
{
"name": "commit",
"license": "MIT",
"metadata": {
"author": "Rob Easthope",
"version": "0.1.2"
},
"description": "Turn the working tree into logical, atomic Conventional Commits — classify uncommitted files as in-scope vs out-of-scope against the branch's merge base, show a staging plan, and create one commit per coherent unit (type + optional scope + British-English body; `!` \/ `BREAKING CHANGE:` for breaking changes). Never `git add -A`; files that look like they belong to another branch\/worktree are never staged silently. Use when asked to commit uncommitted work, tidy WIP into atomic commits, or as the commit step inside a ship flow (e.g. `\/send-it`). It commits only — no push, PR, changelog, or Linear writeback.",
"allowed-tools": "Read, Bash(git:*)",
"compatibility": "Requires the `git` CLI for status\/diff\/merge-base analysis and to create the commits. Contract-only skill — there is no bundled script and no npm dependency; the grouping logic is model-driven and this prose is the source of truth."
}
commit
Turn whatever is uncommitted in the working tree into logical, atomic Conventional Commits — but only the files that belong to this branch. The non-obvious value is the out-of-scope guard: multi-worktree and multi-agent setups can leave stray files in the working tree that belong to another branch, and this skill never sweeps them into a commit.
This skill is the single source of truth for the commit-grouping contract. It is invoked two ways:
- Standalone (
/commit) — "commit my WIP nicely." It creates the commits on the current branch and stops. It never pushes, opens a PR, writes a changelog, or touches Linear. - Inside a ship flow (e.g.
/send-it) — the commit step that runs before the lint gate, so the branch is clean before the changelog/PR work begins. The ship flow owns everything after the commits (lint, changelog, push, PR, Linear); this skill owns only the staging decision and the commits.
Configuration
One knob lives in config.json beside this skill (a neutral
config.example.json ships as a template):
| Key | Meaning | Default |
|---|---|---|
baseBranch |
The trunk the branch diff is taken against (origin/<baseBranch>), used to compute the merge base for scope classification. |
"main" |
Throughout this document <base> is the baseBranch value.
When a ship flow delegates to this skill (e.g. /send-it), it may direct the
classification against a different base for that run — for instance send-it's
--base for a stacked PR. Honour the base the caller resolves; fall back to
config.json baseBranch only for a standalone /commit run.
Process
git status --porcelain. If clean, there is nothing to commit — say so and stop.- Inspect the uncommitted files:
git status --porcelainfor the list,git diffandgit diff --cachedfor the hunks. - Filter for branch relevance. Decide which uncommitted files are in scope:
- Compute the merge base:
git merge-base HEAD origin/<base>. - Files the branch has already touched directly:
git diff --name-only <merge-base>...HEAD. - In scope by default: an uncommitted file whose path is in that branch-touched list.
- Out of scope (uncertain): everything else once the branch has its own commits. This deliberately includes a file that merely sits in a directory the branch has touched but is not itself a path the branch changed — a shared directory is not enough to claim a file. A stray file from another branch or worktree can easily land in a directory this branch happens to have edited, and silently sweeping it in is exactly the out-of-scope leak this guard exists to prevent. Treat directory-only matches as out of scope unless the user explicitly confirms them.
- Fresh branch (no commits of its own yet): there is no branch-touched list to diff against, so nothing distinguishes your own work from a stray file left by another branch or worktree. Do not auto-promote every uncommitted file to in scope — that is exactly the leak this guard exists to catch. Treat all uncommitted files as uncertain and have the user confirm which belong before staging any of them.
- Compute the merge base:
- Show the user the staging plan: in-scope files grouped by proposed commit, plus an explicit list of out-of-scope / uncertain files flagged as "uncertain — possibly from another branch/worktree." Ask: "Stage in-scope files and create the commits below? (yes / no / customise)". Uncertain files are never staged automatically. On a fresh branch the uncertain list is every uncommitted file (step 3): ask the user to confirm which belong, and treat only the confirmed files as in scope.
- Group in-scope files into logical atomic commits:
- One commit per coherent unit (a feature, a bug fix, a refactor, a docs change, a tooling tweak). Don't bundle unrelated edits.
- Use Conventional Commits subjects (
feat:,fix:,chore:,docs:,refactor:,perf:,test:), with a scope when one is obvious (feat(commit): …). - For a breaking change, mark it honestly: a
!after the type/scope (feat(api)!: …) and/or aBREAKING CHANGE:footer in the body. A ship flow reads the bump signal back out of these commit messages, so the markers must be accurate.
- On confirmation, create the commits with
git add <specific files>(nevergit add -A) andgit commit. Stage only the files named in the plan; out-of-scope files stay in the working tree, untouched. Pass one-mper block to add a body or footer beyond the subject —git commit -m "<subject>" -m "<body>", and for a breaking changegit commit -m "feat(api)!: <subject>" -m "BREAKING CHANGE: <what changed and the migration>"(orgit commit -F <message-file>for a longer body). A baregit commit -m "<subject>"is fine when no body is needed.
If a pre-commit hook reformats files, the commit still succeeds with the formatted content.
Commit-message prose
Author commit subjects and bodies in the consuming repo's documented prose
language. Across this estate that is British English (colour, behaviour,
-ise/-yse). This governs prose only — never identifiers, dependency names, or
upstream API field names.
Grouping granularity — per-component splitting is parked
/commit groups by intent (one commit per coherent change), not by component
or package boundaries. Per-component atomic-commit splitting (attributing files to
a package and cutting a commit per package) stays parked (A-374) — no estate
repo does per-component path attribution today. Revisit only if a published
multi-package monorepo doing per-component versioning off squash enters the estate.
Arguments
$ARGUMENTS
版本历史
- c3c0a1e 当前 2026-07-23 10:21


