conventional-commit

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Conventional Commit Skill

Conventional Commit 技能

Overview

概述

Group working-tree changes into Conventional Commits 1.0.0 units (one commit per logical unit), or rewrite recent non-conformant commit subjects in place.
Core principle: Match user intent to the right workflow — new commits vs. history rewrite — and never bypass safety with destructive flags.
Announce at start: "I'm using the conventional-commit skill to <commit / push / rewrite> these changes."
将工作区变更分组为Conventional Commits 1.0.0格式的提交单元(每个逻辑单元对应一个提交),或是就地重写近期不符合规范的提交主题。
核心原则: 将用户意图匹配到正确的工作流——新提交 vs 历史重写——绝不使用破坏性标志绕过安全检查。
启动时告知: "我将使用conventional-commit技能来<提交/推送/重写>这些变更。"

Commands

命令

CommandSkillActionOperates on
/conventional-commit
conventional-commit
Group working-tree changes into Conventional CommitsUncommitted (staged + unstaged) changes
/conventional-commit-push
conventional-commit-push
Same as above, then
git push
(no
--force
)
Uncommitted changes + remote
/conventional-commit-rewrite
conventional-commit-rewrite
Rewrite recent non-Conformant commit subjectsExisting local history
命令技能操作作用对象
/conventional-commit
conventional-commit
将工作区变更分组为Conventional Commits未提交的(已暂存+未暂存)变更
/conventional-commit-push
conventional-commit-push
执行上述操作后,运行
git push
(不使用
--force
未提交变更 + 远程仓库
/conventional-commit-rewrite
conventional-commit-rewrite
重写近期不符合规范的提交主题现有本地提交历史

Choosing the Right Command

选择正确的命令

Run this check before doing anything:
bash
git status --short        # Are there working-tree changes?
git log --oneline -10     # Are recent messages already Conventional?
SituationCommand
Working tree has changes, history is fine
/conventional-commit
Working tree has changes + want to push
/conventional-commit-push
Working tree clean, recent history is messy ("Added X", "WIP", "Fixed bug")
/conventional-commit-rewrite
Both: working tree dirty AND history messyFirst commit (
/conventional-commit
), then
/conventional-commit-rewrite
separately
Auto-routing: If the user runs bare
/conventional-commit
but the working tree is clean, look at recent history. If recent commits are non-conformant, surface this and ask: "No working changes to commit. Recent history has N non-Conformant subjects — do you want to rewrite them with
/conventional-commit-rewrite
?"
执行任何操作前先运行以下检查:
bash
git status --short        # 是否存在工作区变更?
git log --oneline -10     # 近期提交消息是否已经符合Conventional规范?
场景命令
工作区有变更,提交历史无问题
/conventional-commit
工作区有变更且需要推送
/conventional-commit-push
工作区干净,近期提交历史混乱(如"Added X"、"WIP"、"Fixed bug")
/conventional-commit-rewrite
工作区有变更且提交历史混乱先执行
/conventional-commit
提交变更,再单独执行
/conventional-commit-rewrite
自动路由: 如果用户执行了基础的
/conventional-commit
但工作区无变更,则检查近期提交历史。如果近期提交不符合规范,告知用户并询问:"当前没有可提交的工作区变更。近期有N条不符合规范的提交主题——是否需要使用
/conventional-commit-rewrite
重写它们?"

Conventional Commits Format

Conventional Commits 格式

<type>[optional scope][!]: <description>

[optional body]

[optional footer(s)]
Allowed types
TypeMeaning
feat
New feature (MINOR semver bump)
fix
Bug fix (PATCH semver bump)
docs
Documentation only
style
Formatting / whitespace; no logic change
refactor
Code change that neither fixes a bug nor adds a feature
perf
Performance improvement
test
Adding or fixing tests
build
Build system or external dependencies
ci
CI configuration files and scripts
chore
Other changes that don't modify src or tests
revert
Reverts a previous commit
Breaking changes — append
!
after type/scope (e.g.
feat(api)!: drop v1 endpoints
) and/or include a
BREAKING CHANGE: ...
footer.
Subject rules
  • Imperative mood: "add", not "added" / "adds"
  • Lowercase first word of description
  • No trailing period
  • Aim for ≤72 characters in the subject line
  • Scope is optional but recommended when it scopes to a clear module/area
Examples
feat(parser): add ability to parse arrays
fix(ui): correct button alignment
docs: update README with usage instructions
refactor(auth): extract token validation
chore: update dependencies
feat!: send email on registration

BREAKING CHANGE: email service is now required at boot
<类型>[可选范围][!]: <描述>

[可选正文]

[可选页脚]
允许的类型
类型含义
feat
新功能(对应语义化版本的MINOR版本升级)
fix
修复Bug(对应语义化版本的PATCH版本升级)
docs
仅修改文档
style
格式调整/空白字符修改;无逻辑变更
refactor
既不修复Bug也不添加功能的代码变更
perf
性能优化
test
添加或修复测试
build
构建系统或外部依赖变更
ci
CI配置文件和脚本变更
chore
其他不修改源码或测试的变更
revert
回滚之前的提交
破坏性变更——在类型/范围后添加
!
(例如
feat(api)!: drop v1 endpoints
),和/或添加
BREAKING CHANGE: ...
页脚。
主题规则
  • 使用祈使语气:"add",而非"added" / "adds"
  • 描述的首字母小写
  • 末尾无句号
  • 主题行长度尽量控制在≤72字符
  • 范围为可选,但当变更明确指向某个模块/区域时建议添加
示例
feat(parser): add ability to parse arrays
fix(ui): correct button alignment
docs: update README with usage instructions
refactor(auth): extract token validation
chore: update dependencies
feat!: send email on registration

BREAKING CHANGE: email service is now required at boot

Workflow:
/conventional-commit
(default)

工作流:
/conventional-commit
(默认)

Step 1: Inspect the working tree

步骤1:检查工作区

bash
git status --short
git diff
git diff --cached
If there are no changes → tell the user, run the auto-routing check (above), and stop.
bash
git status --short
git diff
git diff --cached
如果没有变更→告知用户,执行上述自动路由检查,然后停止操作。

Step 2: Group changes into logical units

步骤2:将变更分组为逻辑单元

Read each modified file's diff and group by intent. Each group maps to one Conventional Commit. Ignore the existing staging state — staged + unstaged changes are merged and re-grouped from scratch.
Grouping rules:
  • Separate
    feat
    from
    fix
    — never combine
  • Separate
    docs
    from code changes (unless the doc is a docstring inside the same change)
  • Tests for a new feature/fix may go with that commit, or stand alone if unrelated
  • Separate
    build
    /
    ci
    / dependency updates from feature work
  • Separate
    refactor
    from
    feat
  • Fixes in unrelated modules → separate commits per module
  • Trivial whitespace inside a feature file can fold into the feature commit
Don't over-split (a one-line trivial cleanup with the feature is fine) and don't over-combine (a
feat
and
fix
must be separate commits).
Secrets check — flag any of these and exclude by default unless the user explicitly confirms:
.env*
,
credentials.*
,
*_rsa
,
*.pem
,
*.key
,
*.p12
, files containing the word
secret
in the path. Warn the user; they should not be committed.
读取每个修改文件的diff并按意图分组。每个组对应一个Conventional Commit。忽略现有的暂存状态——已暂存和未暂存的变更会被合并并重新从头分组。
分组规则:
  • feat
    fix
    分开——绝不能合并
  • docs
    和代码变更分开(除非文档是同一变更中的注释)
  • 新功能/Bug修复的测试可以与对应提交放在一起,若无关则单独提交
  • build
    /
    ci
    /依赖更新与功能开发分开
  • refactor
    feat
    分开
  • 无关模块中的Bug修复→每个模块单独提交
  • 功能文件中的无关空白字符修改可以合并到功能提交中
不要过度拆分(一行无关的清理与功能放在一起是可以的),也不要过度合并(
feat
fix
必须分开提交)。
机密检查——默认标记并排除以下内容,除非用户明确确认:
.env*
credentials.*
*_rsa
*.pem
*.key
*.p12
、路径中包含
secret
的文件。向用户发出警告;这些内容不应被提交。

Step 3: Show the commit plan

步骤3:展示提交计划

Before creating any commit, print a plan and let the user object:
Plan: 3 commits

1. feat(auth): add OAuth login flow
   - src/auth/oauth.ts
   - src/auth/index.ts

2. fix(api): handle null response in user fetch
   - src/api/users.ts

3. docs: update README with auth setup
   - README.md
在创建任何提交之前,打印计划并让用户确认:
计划:3个提交

1. feat(auth): add OAuth login flow
   - src/auth/oauth.ts
   - src/auth/index.ts

2. fix(api): handle null response in user fetch
   - src/api/users.ts

3. docs: update README with auth setup
   - README.md

Step 4: Create commits one at a time

步骤4:逐个创建提交

For each unit, in plan order:
bash
git add path/one path/two   # explicit paths only
git commit -m "$(cat <<'EOF'
type(scope): description

optional body explaining the why
EOF
)"
Rules:
  • Never
    git add .
    or
    git add -A
    — always explicit paths
  • Never
    --no-verify
    ,
    --no-gpg-sign
    ,
    --amend
    (unless the user explicitly asks)
  • Never add emoji or
    Co-Authored-By: Claude
    unless requested
  • HEREDOC for multi-line messages so quoting stays correct
  • After each commit, run
    git status --short
    to confirm only the intended files moved
If a pre-commit hook fails: do not retry with
--no-verify
. Investigate, fix the underlying issue (or report it), and create a fresh commit.
按照计划顺序,为每个单元执行:
bash
git add path/one path/two   # 仅使用明确的路径
git commit -m "$(cat <<'EOF'
type(scope): description

optional body explaining the why
EOF
)"
规则:
  • 绝不使用
    git add .
    git add -A
    ——始终使用明确路径
  • 绝不使用
    --no-verify
    --no-gpg-sign
    --amend
    (除非用户明确要求)
  • 绝不添加emoji或
    Co-Authored-By: Claude
    ,除非用户要求
  • 使用HEREDOC编写多行消息以保证引号正确
  • 每次提交后,运行
    git status --short
    确认只有预期文件被提交
如果预提交钩子失败:绝不使用
--no-verify
重试。调查并修复根本问题(或报告问题),然后创建新的提交。

Step 5: Final summary

步骤5:最终总结

bash
git log --oneline -<N>
(where
N
is the number of commits made) and show it to the user.
bash
git log --oneline -<N>
(其中
<N>
是创建的提交数量)并将结果展示给用户。

Worked Example

示例流程

User: 변경사항 의미 단위로 커밋해줘

git status --short →
 M src/auth/oauth.ts
 M src/auth/index.ts
 M src/api/users.ts
 M README.md
?? src/api/.env

→ Detect .env (secret) — exclude, warn
→ Group:
   1. feat(auth): add OAuth login flow  (oauth.ts, auth/index.ts)
   2. fix(api): handle null response in user fetch  (users.ts)
   3. docs: update README with auth setup  (README.md)
→ Show plan, wait for confirmation
→ For each: git add <paths> && git commit -m "..."
→ git log --oneline -3
用户:变更사항 의미 단위로 커밋해줘

git status --short →
 M src/auth/oauth.ts
 M src/auth/index.ts
 M src/api/users.ts
 M README.md
?? src/api/.env

→ 检测到.env(机密文件)——排除并警告用户
→ 分组:
   1. feat(auth): add OAuth login flow  (oauth.ts, auth/index.ts)
   2. fix(api): handle null response in user fetch  (users.ts)
   3. docs: update README with auth setup  (README.md)
→ 展示计划,等待用户确认
→ 对每个组执行:git add <paths> && git commit -m "..."
→ git log --oneline -3

Workflow:
/conventional-commit-push

工作流:
/conventional-commit-push

Run the default workflow above. After every commit succeeds:
bash
git push
If the current branch has no upstream configured:
bash
git push -u origin "$(git branch --show-current)"
Never use
--force
or
--force-with-lease
. If the push is rejected (non-fast-forward), stop and report — do not auto-resolve. If the push fails for any reason, surface the error and let the user decide.
先执行上述默认工作流。所有提交成功后:
bash
git push
如果当前分支没有配置上游仓库:
bash
git push -u origin "$(git branch --show-current)"
绝不使用
--force
--force-with-lease
。如果推送被拒绝(非快进式),停止操作并报告——不要自动解决。如果推送因任何原因失败,显示错误并让用户决定下一步。

Worked Example

示例流程

User: /conventional-commit-push

(Same workflow as default, then:)
→ git push
   error: failed to push some refs (non-fast-forward)
→ STOP. Report:
   "Push rejected: branch is behind origin. Run `git pull --rebase`
    first, then re-push manually. I will not auto-resolve."
用户:/conventional-commit-push

(执行与默认工作流相同的步骤,然后:)
→ git push
   error: failed to push some refs (non-fast-forward)
→ 停止操作并报告:
   "推送被拒绝:分支落后于远程仓库。请先执行`git pull --rebase`,然后手动重新推送。我不会自动解决此问题。"

Workflow:
/conventional-commit-rewrite

工作流:
/conventional-commit-rewrite

Rewrites non-Conformant commit messages in recent history. This is destructive — it changes commit SHAs. The default policy refuses to touch any commit that already exists on a remote.
重写近期提交历史中不符合规范的提交消息。这是破坏性操作——会更改提交SHA值。默认策略不会修改任何已推送到远程仓库的提交。

Step 1: Determine the rewrite range

步骤1:确定重写范围

Default base:
bash
upstream=$(git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null || true)
if [ -n "$upstream" ]; then
  base=$(git merge-base HEAD "$upstream")
elif git rev-parse --verify main >/dev/null 2>&1; then
  base=$(git merge-base HEAD main)
elif git rev-parse --verify master >/dev/null 2>&1; then
  base=$(git merge-base HEAD master)
else
  echo "Could not determine a base. Ask the user for an explicit range." >&2
  exit 1
fi
If the user specifies a count (e.g. "rewrite last 5"), use
HEAD~5
as the base instead. Never use
--root
.
默认基准:
bash
upstream=$(git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null || true)
if [ -n "$upstream" ]; then
  base=$(git merge-base HEAD "$upstream")
elif git rev-parse --verify main >/dev/null 2>&1; then
  base=$(git merge-base HEAD main)
elif git rev-parse --verify master >/dev/null 2>&1; then
  base=$(git merge-base HEAD master)
else
  echo "Could not determine a base. Ask the user for an explicit range." >&2
  exit 1
fi
如果用户指定了数量(例如"rewrite last 5"),则使用
HEAD~5
作为基准。绝不使用
--root

Step 2: Safety checks

步骤2:安全检查

Three checks must pass before rewriting in place:
Check A — Working tree clean:
bash
[ -z "$(git status --porcelain)" ]
Fail → tell user to commit/stash first; stop.
Check B — HEAD attached:
bash
git symbolic-ref -q HEAD >/dev/null
Fail → tell user to checkout a branch; stop.
Check C — No commit in range is on a remote:
bash
for sha in $(git rev-list "$base..HEAD"); do
  if [ -n "$(git branch -r --contains "$sha")" ]; then
    pushed_commits+=("$sha")
  fi
done
If
pushed_commits
is non-empty: do not silently refuse. Show the user this menu:
Found N commits in <base>..HEAD whose subjects are non-Conformant.
M of them are already pushed to a remote:

  abc1234  origin/main  "Added User-Agent Parser"
  def5678  origin/main  "Fixed bug"
  ...

Rewriting published history breaks pulls for collaborators. Options:

  1. Cancel — keep history as-is
  2. Rewrite locally + force-push (destructive; coordinate with team first)
  3. Cherry-pick onto a NEW branch with rewritten messages (safe; original branch untouched)

Which option? (default: 1)
  • Option 1 → exit cleanly
  • Option 2 → require explicit phrase like "yes force push" before continuing; after rewrite, run
    git push --force-with-lease
    (NEVER
    --force
    )
  • Option 3 → see "Branch-based rewrite" below
在就地重写之前必须通过三项检查:
检查A——工作区干净:
bash
[ -z "$(git status --porcelain)" ]
失败→告知用户先提交/暂存变更;停止操作。
检查B——HEAD已关联分支:
bash
git symbolic-ref -q HEAD >/dev/null
失败→告知用户切换到分支;停止操作。
检查C——范围内无提交已推送到远程仓库:
bash
for sha in $(git rev-list "$base..HEAD"); do
  if [ -n "$(git branch -r --contains "$sha")" ]; then
    pushed_commits+=("$sha")
  fi
done
如果
pushed_commits
非空:不要直接拒绝。向用户展示以下选项:
在<base>..HEAD范围内发现N条不符合规范的提交主题。其中M条已推送到远程仓库:

  abc1234  origin/main  "Added User-Agent Parser"
  def5678  origin/main  "Fixed bug"
  ...

重写已发布的提交历史会导致协作者拉取失败。选项:

  1. 取消——保持现有历史不变
  2. 本地重写+强制推送(破坏性操作;请先与团队沟通)
  3. 复制到新分支并重写提交消息(安全操作;原分支不受影响)

选择哪个选项?(默认:1)
  • 选项1→干净退出
  • 选项2→需要用户明确说出诸如"yes force push"之类的语句后再继续;重写后执行
    git push --force-with-lease
    绝不使用
    --force
  • 选项3→参见下文"基于分支的重写"

Step 3: Identify non-conformant commits

步骤3:识别不符合规范的提交

For each commit in
<base>..HEAD
, check the subject against:
^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\([^)]+\))?!?: .+
Skip commits that already match. Skip merge commits (use
git rev-list --no-merges
).
对于
<base>..HEAD
范围内的每个提交,检查主题是否符合以下正则:
^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\([^)]+\))?!?: .+
跳过已符合规范的提交。跳过合并提交(使用
git rev-list --no-merges
)。

Step 4: Generate new messages

步骤4:生成新的提交消息

For each non-conformant commit:
  1. Inspect:
    git show --stat <sha>
    and the diff body if needed
  2. Pick a
    type
    from the table above based on the change content
  3. Pick an optional
    scope
    (module / file area) — omit if unsure
  4. Write a new subject: imperative mood, lowercase, ≤72 chars, no trailing period
  5. Preserve the original commit body verbatim. Only the subject line is rewritten. If the original body is empty, leave it empty.
See the "Mapping Common Non-Conformant Patterns" section below for typical translations.
对于每个不符合规范的提交:
  1. 检查:
    git show --stat <sha>
    ,必要时查看diff内容
  2. 根据变更内容从上方的类型表中选择一个
    type
  3. 选择可选的
    scope
    (模块/文件区域)——不确定则省略
  4. 编写新主题:祈使语气、小写、≤72字符、无末尾句号
  5. 完整保留原始提交的正文内容。仅重写主题行。如果原始正文为空,则保持为空。
以下是常见不符合规范模式的映射参考,用于步骤4生成新主题。

Step 5: Show old → new plan

步骤5:展示旧→新提交计划

Rewrite plan: 3 commits

abc1234  added login feature
       → feat(auth): add login feature

def5678  Fixed bug
       → fix(api): handle null response in user fetch

ghi9012  WIP
       → chore: work-in-progress checkpoint
Wait for explicit confirmation before applying.
重写计划:3个提交

abc1234  added login feature
       → feat(auth): add login feature

def5678  Fixed bug
       → fix(api): handle null response in user fetch

ghi9012  WIP
       → chore: work-in-progress checkpoint
等待用户明确确认后再执行重写。

Step 6: Apply the rewrites (in-place)

步骤6:执行重写(就地)

Build the mapping file at
/tmp/cc-rewrite-map.tsv
. Each non-conformant commit gets one line:
<full-40-char-sha>\t<new full message including preserved body>
The new full message is
<new subject>\n\n<original body>
(or just
<new subject>
if there is no body). Newlines inside the message are escaped as
\n
in the TSV;
rewrite_msg.py
un-escapes them.
Then run (use absolute path to the script):
bash
script="$HOME/.claude/skills/conventional-commit/scripts/rewrite_msg.py"
/tmp/cc-rewrite-map.tsv
创建映射文件。每个不符合规范的提交对应一行:
<完整40位sha>\t<包含保留正文的完整新消息>
完整新消息格式为
<新主题>\n\n<原始正文>
(如果没有原始正文则仅为
<新主题>
)。消息中的换行符在TSV中需转义为
\n
rewrite_msg.py
会将其还原。
然后执行(使用脚本的绝对路径):
bash
script="$HOME/.claude/skills/conventional-commit/scripts/rewrite_msg.py"

Plugin install path may differ; resolve via:

插件安装路径可能不同;可通过以下方式查找:

script=$(find ~/.claude -name rewrite_msg.py -path 'conventional-commit' | head -1)

script=$(find ~/.claude -name rewrite_msg.py -path 'conventional-commit' | head -1)

FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch -f
--msg-filter "python3 '$script'"
"$base..HEAD"

The script reads `$GIT_COMMIT`, looks it up in `/tmp/cc-rewrite-map.tsv`, and prints the new message. Commits not in the map pass through unchanged.

**If `git filter-repo` is available** (preferred over `filter-branch`, which is deprecated): use it instead. But the bundled mapping flow currently relies on `filter-branch`; only switch if the user has `filter-repo` and prefers it.
FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch -f
--msg-filter "python3 '$script'"
"$base..HEAD"

该脚本读取`$GIT_COMMIT`,在`/tmp/cc-rewrite-map.tsv`中查找并打印新消息。不在映射中的提交将保持不变。

**如果`git filter-repo`可用**(比已废弃的`filter-branch`更推荐):使用它替代。但当前的映射流程依赖`filter-branch`;仅当用户安装了`filter-repo`并偏好使用时才切换。

Step 7: Branch-based rewrite (Option 3 from Step 2)

步骤7:基于分支的重写(步骤2中的选项3)

When commits are pushed and the user picks Option 3, do this instead of in-place rewrite:
bash
undefined
当提交已推送到远程仓库且用户选择选项3时,执行以下操作而非就地重写:
bash
undefined

1. Note current branch

1. 记录当前分支

src=$(git branch --show-current)
src=$(git branch --show-current)

2. Create a fresh branch off the upstream/base

2. 基于上游/基准创建新分支

git checkout -b "${src}-cc" "$base"
git checkout -b "${src}-cc" "$base"

3. Cherry-pick each commit, rewriting message as you go

3. 逐个复制提交并同时重写消息

for sha in $(git rev-list --reverse --no-merges "$base..$src"); do new_msg=$(lookup_in_map "$sha") # from Step 4 plan; or compose interactively git cherry-pick "$sha" git commit --amend -m "$new_msg" # only the cherry-pick we just made done
for sha in $(git rev-list --reverse --no-merges "$base..$src"); do new_msg=$(lookup_in_map "$sha") # 来自步骤4的计划;或交互式编写 git cherry-pick "$sha" git commit --amend -m "$new_msg" # 仅修改刚复制的提交
done

4. Verify, then push the new branch

4. 验证后推送新分支

git log --oneline "$base..HEAD" git push -u origin "${src}-cc"

The original branch is untouched. The user can open a PR from `${src}-cc` and abandon the original branch when ready. **No force push, no destruction.**
git log --oneline "$base..HEAD" git push -u origin "${src}-cc"

原分支不受影响。用户可以从`${src}-cc`创建PR,准备就绪后废弃原分支。**无需强制推送,无破坏性操作。**

Step 8: Post-rewrite cleanup

步骤8:重写后清理

After in-place rewrite (Step 6):
  • Run
    git log --oneline "$base..HEAD"
    and show the result.
  • Tell the user a backup ref was kept at
    refs/original/refs/heads/<branch>
    and how to discard it once they're satisfied:
    bash
    git update-ref -d refs/original/refs/heads/<branch>
    Do not delete it automatically.
  • Delete the temp file:
    bash
    rm -f /tmp/cc-rewrite-map.tsv
After branch-based rewrite (Step 7):
  • Tell the user how to switch back if they change their mind:
    bash
    git checkout <original-branch>
    git branch -D <branch>-cc
就地重写(步骤6)后:
  • 执行
    git log --oneline "$base..HEAD"
    并展示结果。
  • 告知用户备份引用已保存至
    refs/original/refs/heads/<branch>
    ,以及确认无误后如何删除:
    bash
    git update-ref -d refs/original/refs/heads/<branch>
    不要自动删除。
  • 删除临时文件:
    bash
    rm -f /tmp/cc-rewrite-map.tsv
基于分支的重写(步骤7)后:
  • 告知用户如果改变主意如何切换回原分支:
    bash
    git checkout <original-branch>
    git branch -D <branch>-cc

Worked Example: messy history

示例流程:混乱的提交历史

User: 커밋 메시지 다시 써줘
       (User shares git log:)
       96b6be8  gnhf #43: Added User-Agent Parser ...
       eda73c5  gnhf #42: Added JSON Schema Generator ...
       e943794  gnhf #41: Added IPv4 Subnet Calculator ...
       0a7e01e  gnhf #40: Added Markdown TOC Generator ...

Step 1 (range):
   upstream = origin/gnhf/prd-chann-tools-2026-8f2964
   base = $(git merge-base HEAD origin/main)

Step 2 (safety):
   ✓ working tree clean
   ✓ HEAD attached
   ✗ all 4 commits exist on origin/<branch>
   → Show menu (Cancel / Force-push / New branch). User picks 3.

Step 3 (regex): all 4 fail the regex (start with "gnhf #N:")

Step 4 (mapping):
   "gnhf #43: Added User-Agent Parser..."   → feat(api-network): add user-agent parser
   "gnhf #42: Added JSON Schema Generator"  → feat(data-format): add JSON schema generator
   "gnhf #41: Added IPv4 Subnet Calculator" → feat(api-network): add IPv4 subnet calculator
   "gnhf #40: Added Markdown TOC Generator" → feat(text): add Markdown TOC generator

   Drop the "gnhf #N" prefix (ticket-tracker noise; belongs in the body or a footer).
   To preserve the ticket reference, add a footer:
       Refs: gnhf#43

Step 5: show old → new plan, wait for confirmation.

Step 7 (branch-based):
   git checkout -b feature-tools-cc origin/main
   for sha in (cherry-pick each, --amend with new message)
   git push -u origin feature-tools-cc
用户:커밋 메시지 다시 써줘
       (用户提供git log:)
       96b6be8  gnhf #43: Added User-Agent Parser ...
       eda73c5  gnhf #42: Added JSON Schema Generator ...
       e943794  gnhf #41: Added IPv4 Subnet Calculator ...
       0a7e01e  gnhf #40: Added Markdown TOC Generator ...

步骤1(范围):
   upstream = origin/gnhf/prd-chann-tools-2026-8f2964
   base = $(git merge-base HEAD origin/main)

步骤2(安全检查):
   ✓ 工作区干净
   ✓ HEAD已关联分支
   ✗ 所有4个提交都已推送到origin/<branch>
   → 展示选项菜单(取消/强制推送/新分支)。用户选择3。

步骤3(正则检查):所有4个提交都不符合正则(以"gnhf #N:"开头)

步骤4(映射):
   "gnhf #43: Added User-Agent Parser..."   → feat(api-network): add user-agent parser
   "gnhf #42: Added JSON Schema Generator"  → feat(data-format): add JSON schema generator
   "gnhf #41: Added IPv4 Subnet Calculator" → feat(api-network): add IPv4 subnet calculator
   "gnhf #40: Added Markdown TOC Generator" → feat(text): add Markdown TOC generator

   移除"gnhf #N"前缀(工单跟踪信息;应放在正文或页脚中)。
   为保留工单关联,添加页脚:
       Refs: gnhf#43

步骤5:展示旧→新计划,等待用户确认。

步骤7(基于分支):
   git checkout -b feature-tools-cc origin/main
   for sha in (逐个复制提交,使用--amend修改消息)
   git push -u origin feature-tools-cc

Mapping Common Non-Conformant Patterns

常见不符合规范模式映射

Use these translations when generating new subjects in Step 4.
Original patternLikely Conventional rewrite
Added X
/
Add X
feat: add X
(or
feat(scope): add X
)
Fixed X
/
Fix X
/
Bugfix: X
fix: <imperative>
Updated X
(cosmetic/dep bump)
chore: update X
or
build(deps): bump X
Updated X
(real refactor)
refactor: <imperative>
Cleanup
/
Clean up X
refactor: <imperative>
or
chore: <imperative>
Renamed X to Y
refactor: rename X to Y
Removed X
/
Delete X
refactor: remove X
(or
feat!:
if breaking)
WIP
/
wip
/
tmp
chore: work-in-progress checkpoint
Initial commit
chore: initial commit
Merge branch 'X'
Skip (merge commits are excluded)
[TICKET-123] Added X
feat: add X
+ footer
Refs: TICKET-123
proj #N: Added X
feat(scope): add X
+ footer
Refs: proj#N
Tests for X
test: add tests for X
Docs: <anything>
docs: <imperative>
Refactor X
(already imperative-ish)
refactor: <imperative form>
Rules of thumb:
  • Past tense → imperative ("Added" → "add", "Fixed" → "fix")
  • Capitalized → lowercase
  • Strip trailing periods
  • Ticket-tracker prefixes → move to a
    Refs:
    footer (don't drop the linkage)
  • If the type is genuinely ambiguous between
    chore
    ,
    refactor
    , and
    style
    , prefer
    chore
    for tooling/config,
    refactor
    for code-shape changes,
    style
    only for whitespace/formatting
在步骤4生成新主题时,可参考以下转换规则。
原始模式对应的Conventional重写
Added X
/
Add X
feat: add X
(或
feat(scope): add X
Fixed X
/
Fix X
/
Bugfix: X
fix: <祈使语气描述>
Updated X
(外观/依赖版本升级)
chore: update X
build(deps): bump X
Updated X
(实际重构)
refactor: <祈使语气描述>
Cleanup
/
Clean up X
refactor: <祈使语气描述>
chore: <祈使语气描述>
Renamed X to Y
refactor: rename X to Y
Removed X
/
Delete X
refactor: remove X
(如果是破坏性变更则用
feat!:
WIP
/
wip
/
tmp
chore: work-in-progress checkpoint
Initial commit
chore: initial commit
Merge branch 'X'
跳过(合并提交已被排除)
[TICKET-123] Added X
feat: add X
+ 页脚
Refs: TICKET-123
proj #N: Added X
feat(scope): add X
+ 页脚
Refs: proj#N
Tests for X
test: add tests for X
Docs: <anything>
docs: <祈使语气描述>
Refactor X
(已接近祈使语气)
refactor: <祈使语气形式>
经验法则:
  • 过去式→祈使语气("Added"→"add","Fixed"→"fix")
  • 大写→小写
  • 移除末尾句号
  • 工单跟踪前缀→移至
    Refs:
    页脚(不要丢失关联)
  • 如果类型在
    chore
    refactor
    style
    之间难以区分,工具/配置变更优先选
    chore
    ,代码结构变更优先选
    refactor
    ,仅空白字符/格式变更选
    style

Quick Reference

快速参考

When stuck, ask:
SymptomAction
No working changes + messy historySuggest
/conventional-commit-rewrite
Working changes + messy historyCommit first, then
/conventional-commit-rewrite
Pushed history + want to fixUse Step 7 (branch-based rewrite)
Pre-commit hook failsFix the underlying issue; never
--no-verify
Push rejected (non-FF)Stop, surface error, never
--force
without explicit consent
git filter-branch
warns about deprecation
FILTER_BRANCH_SQUELCH_WARNING=1
is already set; ignore
遇到问题时,请执行:
症状操作
无工作区变更但提交历史混乱建议使用
/conventional-commit-rewrite
工作区有变更且提交历史混乱先提交变更,再使用
/conventional-commit-rewrite
提交已推送到远程仓库但需要修复使用步骤7(基于分支的重写)
预提交钩子失败修复根本问题;绝不使用
--no-verify
推送被拒绝(非快进式)停止操作,显示错误,未经明确同意绝不使用
--force
git filter-branch
提示已废弃
已设置
FILTER_BRANCH_SQUELCH_WARNING=1
;忽略该警告

Common Mistakes

常见错误

Combining feat + fix in one commit
  • Problem:
    feat(auth): add OAuth and fix null response
    mixes types
  • Fix: Two separate commits, one feat one fix
Past-tense subjects
  • Problem: "added login flow", "fixed bug"
  • Fix: Imperative — "add login flow", "handle null response"
git add .
to stage everything
  • Problem: Accidentally stages secrets or unrelated changes
  • Fix: Always
    git add <explicit-paths>
    per group
Bypassing hooks with
--no-verify
  • Problem: Hides real issues; commit "works" locally but fails CI
  • Fix: Investigate the hook failure; fix root cause; create fresh commit
Silently refusing rewrite of pushed history
  • Problem: Says "I can't" with no path forward
  • Fix: Present the 3-option menu in Step 2 (cancel / force-push / branch-based)
Dropping ticket references during rewrite
  • Problem: "gnhf #43: Added X" → "feat: add X" loses the
    gnhf#43
    linkage
  • Fix: Move ticket to a
    Refs: gnhf#43
    footer; don't lose it
Rewriting merge commits
  • Problem: Filter-branch on merges scrambles parent linkage
  • Fix:
    git rev-list --no-merges
    always
将feat和fix合并到一个提交中
  • 问题:
    feat(auth): add OAuth and fix null response
    混合了不同类型
  • 修复: 拆分为两个独立提交,一个feat一个fix
使用过去式主题
  • 问题: "added login flow"、"fixed bug"
  • 修复: 使用祈使语气——"add login flow"、"handle null response"
使用
git add .
暂存所有内容
  • 问题: 意外暂存机密文件或无关变更
  • 修复: 始终为每个分组使用
    git add <明确路径>
使用
--no-verify
绕过钩子
  • 问题: 隐藏真实问题;本地提交成功但CI失败
  • 修复: 调查钩子失败原因;修复根本问题;创建新提交
直接拒绝重写已推送的提交历史
  • 问题: 仅说"我不能"但不提供解决方案
  • 修复: 展示步骤2中的三选项菜单(取消/强制推送/基于分支)
重写时丢失工单引用
  • 问题: "gnhf #43: Added X"→"feat: add X"丢失了
    gnhf#43
    关联
  • 修复: 将工单信息移至
    Refs: gnhf#43
    页脚;不要丢失关联
重写合并提交
  • 问题: 在合并提交上使用filter-branch会打乱父提交关联
  • 修复: 始终使用
    git rev-list --no-merges

Red Flags

注意事项

Never:
  • git add .
    or
    git add -A
    (use explicit paths)
  • --no-verify
    ,
    --no-gpg-sign
    ,
    --amend
    without explicit user consent
  • --force
    push (
    --force-with-lease
    only after explicit consent)
  • Commit
    .env*
    ,
    credentials.*
    ,
    *_rsa
    ,
    *.pem
    ,
    *.key
    ,
    *.p12
    without explicit user override
  • Combine
    feat
    and
    fix
    in one commit
  • Rewrite pushed commits without showing the 3-option menu first
  • Use
    git filter-branch --root
  • Drop ticket references during rewrite (move them to
    Refs:
    footer)
Always:
  • Show a commit plan before creating commits
  • Run
    git status --short
    after each commit to verify
  • Preserve the original commit body verbatim during rewrite
  • Use
    --no-merges
    when listing commits to rewrite
  • Default to "Cancel" when prompting on pushed commits
  • Match the repo's existing scope conventions (
    git log -20 --oneline
    first)
绝不:
  • 使用
    git add .
    git add -A
    (使用明确路径)
  • 未经用户明确同意使用
    --no-verify
    --no-gpg-sign
    --amend
  • 使用
    --force
    推送(仅在用户明确同意后使用
    --force-with-lease
  • 未经用户明确覆盖提交
    .env*
    credentials.*
    *_rsa
    *.pem
    *.key
    *.p12
  • feat
    fix
    合并到一个提交中
  • 未展示三选项菜单就重写已推送的提交
  • 使用
    git filter-branch --root
  • 重写时丢失工单引用(移至
    Refs:
    页脚)
始终:
  • 创建提交前展示提交计划
  • 每次提交后运行
    git status --short
    验证
  • 重写时完整保留原始提交的正文内容
  • 列出要重写的提交时使用
    --no-merges
  • 提示处理已推送提交时默认选择"取消"
  • 匹配仓库现有的范围约定(先执行
    git log -20 --oneline

Behavior Notes

行为说明

Match the repo's existing style. Inspect
git log -20 --oneline
first. If the repo uses Conventional Commits, mirror its scope conventions. If existing messages are mixed, default to lowercase descriptions and concise scopes.
Narration vs. commit-message language. Conversation updates: user's prompt language. Commit messages: language already dominant in
git log
(English when ambiguous).
Be conservative with scopes. A scope must name a real module/area. If unsure, omit the scope rather than invent one.
Don't over-explain in bodies. A body should add context the subject can't carry (the why, a tricky tradeoff, related issue). If the subject is self-explanatory, no body.
Refuse, don't bypass. If a safety check fails (pushed commits without consent, dirty tree, detached HEAD, suspected secret), report and stop. Do not work around with destructive flags.
Trust explicit user override. "Force push", "yes I know it's pushed, rewrite anyway", "include the .env this time" → proceed, but state the risk in one line first.
匹配仓库现有风格。先执行
git log -20 --oneline
检查。如果仓库使用Conventional Commits,遵循其范围约定。如果现有消息混合,默认使用小写描述和简洁范围。
对话语言与提交消息语言。对话更新:使用用户提示的语言。提交消息:使用
git log
中占主导的语言(不确定时使用英文)。
范围使用要保守。范围必须指向真实的模块/区域。不确定时省略范围,不要凭空创造。
正文不要过度解释。正文应添加主题无法传达的上下文(原因、复杂的权衡、相关问题)。如果主题已能自解释,则无需正文。
拒绝而非绕过。如果安全检查失败(未经同意重写已推送提交、工作区不干净、HEAD分离、疑似机密文件),报告并停止操作。不要使用破坏性标志绕过。
尊重用户明确的覆盖要求。"Force push"、"yes I know it's pushed, rewrite anyway"、"include the .env this time"→执行操作,但先以一行文字说明风险。

Integration

集成

Pairs with:
  • code-review — Run
    /code-review
    before committing as a final quality gate
  • Any plugin commit hooks (commitlint, husky) — fix violations rather than
    --no-verify
Called by: Manual user invocation only. Never auto-run during another skill's workflow.
搭配使用:
  • code-review——提交前运行
    /code-review
    作为最终质量检查
  • 任何插件提交钩子(commitlint、husky)——修复违规而非使用
    --no-verify
调用方式: 仅由用户手动触发。绝不会在其他技能的工作流中自动运行。