# Chinese Commit

> 写 git commit 时使用。生成规范的 Conventional Commits(英文 type + 中文主题),主题精炼。

- Skill: `wade-devcode/chinese-commit` (Agent Skill)
- Install (CLI): `npx skillmds@latest add wade-devcode/chinese-commit`
- Raw SKILL.md: https://api.skillmd.com/api/skills/wade-devcode/chinese-commit/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: Wade-DevCode (https://skillmd.com/u/wade-devcode)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/wade-devcode/chinese-commit

---


# 中文 commit 规范

## 何时用

- 准备执行 `git commit` 前，需要撰写 commit message 时。
- 对已有 commit message 做 review 或修改时。
- 在 PR 描述中引用 commit 列表，需要判断某条消息是否清晰时。
- 给团队新成员讲解项目提交规范时。

## 核心规则

### 1. 格式 = `type(scope): 中文主题`

**规则：** type 必须用英文关键字（`feat` / `fix` / `docs` / `refactor` / `test` / `chore` / `perf`），冒号后的主题用中文，且不超过 50 个字。

**为什么：** AI 最常见的错误有两种：一是整行全写中文（`新增功能：用户登录`），导致 CI 的 commit-lint 规则直接报错；二是 type 用中文近义词（`特性`、`修复`）或随意缩写（`f`、`upd`），让 `git log --oneline` 的过滤脚本无法识别。格式不统一还会导致自动生成 CHANGELOG 时分类错误，把 bug 修复误放进"新功能"节。

**怎么做：**
- type 只从以下七个中选一个：`feat`（新功能）、`fix`（缺陷修复）、`docs`（文档）、`refactor`（重构，不改行为）、`test`（测试）、`chore`（构建/工具链）、`perf`（性能优化）。
- scope 写在圆括号内，可省略，但存在时必须用真实模块名（见规则 5）。
- 冒号后面跟一个空格，然后是中文主题，不加句号。

---

### 2. 主题写"做了什么"，用祈使句

**规则：** 主题用一句祈使句描述本次变更的核心动作，不写流水账，不写"修改了一些文件"之类的废话。

**为什么：** AI 极容易生成这种主题：`更新了登录模块的相关代码`——这句话在任何 commit 上都成立，完全没有信息量。另一类错误是记流水账：`修改了 auth.py，删除了多余的注释，调整了变量名，顺便加了一个空行`。主题不是 diff 摘要，是对"本次提交解决了什么问题"的一句话答案。读 `git log --oneline` 时，好的主题应当让人一眼知道"要不要点进这个 commit 看细节"。

**怎么做：**
- 问自己：「这个 commit 的目的是什么？」把答案压缩成一句话。
- 动词放句首，例如：`修复`、`新增`、`删除`、`提取`、`替换`、`禁用`。
- 不带末尾句号；不用被动句（不写"被修复了"）。
- 超过 50 字说明你在一次 commit 里做了多件事，应当拆分（见规则 4）。

---

### 3. 正文只在"为什么"不显然时写

**规则：** commit 正文（body）用来解释动机与权衡，而不是复述 diff 的内容。若改动理由一眼即明，正文可省略。

**为什么：** AI 倾向于把 diff 内容逐行翻译成正文，例如：`将 token_expiry < now 改为 token_expiry <= now`——这完全没有价值，读者直接看 diff 就能得到这个信息。真正有用的正文是：`旧逻辑在 token 恰好等于当前时间时不视为过期，导致极少数请求绕过鉴权；改为 <= 后临界情况被正确拦截。` 这类信息只存在于作者脑子里，不写下来就永久丢失。

**怎么做：**
- 主题行与正文之间空一行（git 规范要求）。
- 正文用自然段落，每行不超过 72 字，方便 `git log` 展示。
- 只写"为什么这样改"和"考虑过哪些替代方案、为何放弃"，不复述 diff。
- 如果有关联的 issue 或 PR，在正文末尾用 `Closes #123` / `Refs #456` 标注。

---

### 4. 一次只提一件事

**规则：** 一个 commit 只做一件逻辑上内聚的事；功能、修复、格式整理混在一起时，必须拆成多个 commit。

**为什么：** AI 在帮用户完成任务时容易"顺手"把格式清理、变量重命名、无关 bug 修复一并提交。这类混合 commit 带来三个具体问题：① `git bisect` 时无法精确定位引入 bug 的节点；② cherry-pick 到其他分支时会带入不需要的副作用；③ code review 时 reviewer 不知道应该关注功能正确性还是格式合规，两件事互相干扰。

**怎么做：**
- 在提交前用 `git diff --staged` 扫描暂存区：确认每一处修改都服务于同一个目的。
- 发现夹带了无关改动（例如顺手修了 typo），用 `git add -p` 把它们拆到单独的 commit。
- 格式化改动（`chore: 统一缩进风格`）单独提交，绝不与功能 commit 混在一起。

---

### 5. scope 用真实模块名

**规则：** scope 必须对应项目中真实存在的目录名、模块名或服务名；不编造模糊范围，不用 `misc`、`various`、`global` 之类的占位词。

**为什么：** AI 在不确定影响范围时会编造一个听起来合理的 scope，例如 `fix(backend): …`——但项目里根本没有叫 `backend` 的目录，实际改的是 `api/auth` 模块。这让基于 scope 过滤 CHANGELOG 的脚本输出混乱，也让后续维护者无法通过 `git log --grep` 快速锁定某模块的历史变更。

**怎么做：**
- 打开项目根目录，用真实的顶层目录名或模块名作为 scope，例如 `auth`、`user`、`payment`、`db`、`cli`。
- 若改动跨多个模块且无法归为某一个，省略 scope，不要编造一个"最近似"的假名。
- monorepo 中 scope 通常是包名，例如 `@app/core`，直接用包的短名：`core`。

---

## 正例 / 反例

### 第一组：主题无信息量 vs. 直击要害

```
# 反例 — 读者毫无所知，在任何 repo 的任何 commit 上都能贴
update code

# 反例 — 流水账，不说明做了什么，也不说明为什么
改了一堆东西，调整了登录页，还顺便修了一个 bug
```

```
# 正例 — 一眼知道改了哪个模块、解决了什么问题
fix(auth): 修复 token 过期判断用 < 导致临界失效

# 正例 — 新功能，主题完整交代了做什么、作用在哪里
feat(payment): 新增支付宝扫码支付入口
```

---

### 第二组：type 错误 vs. 准确选型

```
# 反例 — type 用中文，CI lint 直接挂
新增: 用户头像上传功能

# 反例 — type 含糊，无法区分功能还是修复
update(profile): 更新了头像上传的逻辑
```

```
# 正例 — type 精准，读者立即知道这是新功能
feat(profile): 支持上传 WebP 格式头像并自动压缩至 200 KB 以内

# 正例 — 重构不改行为，用 refactor 区分于 feat/fix
refactor(db): 将裸 SQL 查询提取为 Repository 层统一管理
```

---

### 第三组：带正文的完整 commit（解释 why）

```
fix(session): 修复并发登录时 session 互相覆盖的问题

旧实现使用用户 ID 作为 session key，同一账号在两台设备同时登录时，
后登录的设备会覆盖前一个设备的 session，导致前者被强制下线但无任何提示。

改为在 session key 中加入设备指纹（device_fingerprint），使每台设备
持有独立的 session。考虑过改用 JWT 无状态方案，但当前需要服务端主动
撤销能力，暂不切换。

Closes #412
```

---

## 自查清单

- [ ] type 是七个英文关键字之一：`feat` / `fix` / `docs` / `refactor` / `test` / `chore` / `perf`。
- [ ] 主题是中文祈使句，不超过 50 字，末尾没有句号。
- [ ] scope（若有）对应项目中真实存在的目录名或模块名，没有编造占位词。
- [ ] 本次 commit 只做一件逻辑内聚的事，格式改动和功能改动没有混在一起。
- [ ] 如果写了正文，正文解释的是"为什么"而不是逐行复述 diff 内容。
- [ ] 主题行与正文之间有且仅有一行空行（若有正文）。
- [ ] 关联的 issue 或 PR 已在正文末尾用 `Closes #N` / `Refs #N` 标注（若有）。

