git-commit

Draft a commitlint-compliant Chinese commit message from staged (or working tree) changes and run git commit by default, using Lore decision trailers when they add material context—never Co-authored-b

SKILL.md

GitHub

Git Commit

Default: draft the smallest Lore-compliant message → validate → commit → verify clean → git commit-tree rewrite if polluted.

Do not commit when the user says not to (e.g. 不要提交、仅生成信息、只给 message、draft only).

Use a subject-only message for routine changes with no useful decision context. Add a concise body and Lore trailers when constraints, rejected alternatives, risk, directives, or verification evidence would help future modifiers; user permission is not required to record relevant context.

Workflow

  1. Read commitlint.config.mjs (Conventional Commits if @commitlint/config-conventional).
  2. Change source: staged if git diff --cached --quiet exits nonzero; else full working tree (stage first when committing).
  3. Gather context (commands below).
  4. Write Chinese subject/body — no AI shadow (see below).
  5. Write the smallest message that preserves relevant decision context: subject only for routine work; otherwise a concise body plus applicable Lore trailers from docs/ai/core/git-protocol.md.
  6. Validate the complete message with pnpm commitlint (revise until pass).
  7. Commit — subject only when no body is needed:
    git commit -m '<subject>'
    
    Multiline when Lore context is useful or the user requests detail:
    git commit -m '<subject>' -m '<body>'
    
  8. Verify & strip (mandatory) — see Strip IDE injection. Do not report success until the latest commit message is clean.
  9. Message-only request → output validated message in a fenced text block and stop (no commit).

Strip IDE injection (mandatory)

IDEs (especially Cursor) append trailers after every git commit / git commit --amend, e.g. Co-authored-by: Cursor <cursoragent@cursor.com> or Made-with: Cursor. git commit --amend -m does not remove them — Cursor re-injects on each amend.

After every git commit:

git log -1 --format=%B

Polluted if output matches any of (case-insensitive):

  • Co-authored-by:
  • Made-with:
  • cursoragent@cursor.com
  • Generated-by: · Assisted-by: · AI- attribution footers

If polluted — rewrite HEAD with git commit-tree (bypasses hooks and Cursor injection):

# Single-line (default) — replace <subject> with validated message
OLD=$(git rev-parse HEAD)
TREE=$(git rev-parse 'HEAD^{tree}')
PARENT=$(git rev-parse 'HEAD^')   # omit -p when rewriting root commit
export GIT_AUTHOR_NAME="$(git log -1 --format='%an' "$OLD")"
export GIT_AUTHOR_EMAIL="$(git log -1 --format='%ae' "$OLD")"
export GIT_AUTHOR_DATE="$(git log -1 --format='%at' "$OLD")"
export GIT_COMMITTER_NAME="$(git log -1 --format='%cn' "$OLD")"
export GIT_COMMITTER_EMAIL="$(git log -1 --format='%ce' "$OLD")"
export GIT_COMMITTER_DATE="$(git log -1 --format='%ct' "$OLD")"
NEW=$(printf '%s\n' '<subject>' | git commit-tree "$TREE" -p "$PARENT")
git reset --hard "$NEW"

Multiline: reproduce the complete validated subject/body/trailers through git commit-tree.

Re-run git log -1 --format=%B until only the intended subject/body remain.

Do not loop git commit --amend -m expecting trailers to disappear in Cursor — use commit-tree immediately when pollution is detected.

Amend rules: strip-injection rewrite is allowed on a commit you just created in this task, even if the user did not say “amend”. Do not rewrite older commits or pushed history unless the user explicitly requests cleanup.

Forbidden:

  • Leaving Co-authored-by / Made-with in history you created
  • --trailer, --signoff (unless user asked), extra -m lines for attribution
  • Reporting “done” while git log -1 still shows AI trailers

Cursor (human): disable Settings → Agents → Attribution → Commit attribution to reduce injection at source. The skill still must verify and strip with commit-tree regardless.

Message Rules

<type>(optional-scope): <subject>

Types: feat · fix · docs · style · refactor · perf · test · build · ci · chore

Subject: Chinese, imperative, concise, no trailing period, no AI/tool mentions.

No AI Shadow

Messages must read as human-authored history — only what changed, never who assisted.

Never write or leave in history:

  • Co-authored-by: (Cursor, Codex, Claude, ChatGPT, Copilot, any agent email)
  • Made-with: Cursor or similar product trailers
  • Generated-by:, Assisted-by:, tool names in footers
  • “generated by …”, “written with …” in subject/body

Short-log: use a subject only when the change has no material decision context.

Body: include only useful decision context; each line ≤100 chars (body-max-line-length). Use Lore trailers selectively as defined by docs/ai/core/git-protocol.md.

Context Commands

sed -n '1,120p' commitlint.config.mjs
git status --short
git diff --cached --quiet
git diff --cached --stat
git diff --cached --find-renames --find-copies
# if no staged:
git diff --stat
git diff --find-renames --find-copies
git ls-files --others --exclude-standard

Staged scope wins. For lockfiles: git diff --stat -- <lockfile>.

Done Checklist

  • pnpm commitlint passed on final message text
  • git log -1 --format=%B has no attribution trailers
  • git status — no unexpected unstaged hook changes (if hook modified files, handle per repo amend rules)