# Git Commit Guidelines

> Use when 用户要求生成或检查 Git 提交消息、拆分或暂存改动、执行 git commit、整理提交历史，或准备提交涉及多个文件、模块或职责的变更

- Skill: `zhanggong0564/git-commit-guidelines` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add zhanggong0564/git-commit-guidelines`
- Raw SKILL.md: https://api.skillmd.com/api/skills/zhanggong0564/git-commit-guidelines/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: zhanggong0564 (https://skillmd.com/u/zhanggong0564)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/zhanggong0564/git-commit-guidelines

---

---------------------------------------------------------------------------------------

# Git 提交

## 核心原则

**一次提交只承载一个可独立审查、验证和回滚的职责。**

目录相同、scope 相同、属于同一功能或同一次发布，都不能证明改动应该放在同一提交中。

判断优先级：

> 职责边界 > 仓库规则 > 变更类型 > 文件数量

当一个提交主题必须使用“和”“以及”“同时”才能描述时，通常说明还需要继续拆分。

## 操作边界

根据用户请求确定操作模式：

| 用户请求                    | 允许的操作                   |
| ----------------------- | ----------------------- |
| 生成、优化或检查 commit message | 只读取状态和差异，不执行暂存或提交       |
| 分析或建议如何拆分提交             | 只输出拆分方案，除非用户同时要求暂存      |
| 暂存或拆分改动                 | 可以执行 `git add`，不得自动提交   |
| 提交代码                    | 可以暂存并执行 `git commit`    |
| 推送代码                    | 只有用户明确要求时才执行 `git push` |
| 拆分、合并或修改已有提交            | 必须先检查历史改写安全条件           |

“提交全部改动”只授权处理全部改动范围，**不代表可以把全部改动压成一个提交**。

始终保留用户已有改动，不清理、不覆盖、不重置、不顺手提交无关内容。

## 仓库规则优先级

提交前必须按以下顺序检查规则：

1. 用户当前指令
2. `AGENTS.md`、`CLAUDE.md`、`GEMINI.md` 等智能体说明
3. `CONTRIBUTING.md`、开发文档和提交模板
4. `commitlint`、Commitizen、语义发布等配置
5. 最近的有效提交历史
6. 本 Skill 的默认规则

建议先运行：

```bash
git status --short --branch
git diff --stat
git diff --cached --stat
git log --oneline -20
```

如果仓库规定了固定的 type、scope、主题语言、长度、正文或署名格式，必须遵守仓库规定。

不要根据个人习惯发明仓库未允许的 type 或 scope。历史提交只能辅助判断，不能覆盖明确的文档和配置。

## 强制执行流程

### 第一步：盘点改动

检查工作区、暂存区和未跟踪文件：

```bash
git status --short
git diff --stat
git diff --name-only
git diff --cached --stat
```

必要时查看具体差异：

```bash
git diff -- path/to/file
git diff --cached -- path/to/file
```

必须同时检查：

* 已修改但未暂存的文件
* 已暂存的文件
* 未跟踪文件
* 用户此前已经暂存的内容
* 同一文件中的多个独立 hunk

不得假设暂存区中的内容都属于当前任务。

### 第二步：识别职责

暂存前，对每组改动依次回答：

1. 能否用一个准确主题描述，且不使用“和”“以及”“同时”？
2. 能否独立审查、验证和回滚？
3. 每个文件或 hunk 是否都直接服务于同一个行为？

任一答案为“否”，必须继续拆分。

以下改动通常具有独立审查和回滚价值：

* 用户功能或缺陷修复
* 配置调整
* 数据库迁移
* 公共接口变更
* 重构
* 性能优化
* 文档
* 测试
* 构建与依赖
* CI 配置
* 发布与部署脚本

同一文件包含多个职责时，必须按 hunk 分析，不能仅按文件路径分组。

### 第三步：输出提交计划

**首次执行任何 `git add` 前，必须先向用户输出提交计划。**

格式：

| 候选提交 | 文件或 hunk       | 单一职责        | 验证命令          | 拟定提交消息                 |
| ---- | -------------- | ----------- | ------------- | ---------------------- |
| 1    | `path/to/file` | 可独立审查和回滚的行为 | 能直接验证该行为的具体命令 | `type(scope): subject` |

要求：

* 每一行对应一个候选提交。
* 一个候选提交可以包含多个文件，但这些文件必须共同构成不可分割的行为。
* 同一文件包含多个职责时，使用不同 hunk 分行。
* 验证命令必须能验证该职责，不能只写“跑测试”“检查功能”等笼统描述。
* `git diff --cached --check` 只能检查补丁质量，不能作为行为验证命令。
* 未输出计划，不得暂存。
* 发现新的职责后，必须更新计划再继续。

### 第四步：逐个暂存

每次只处理一个候选提交。

优先显式暂存路径：

```bash
git add -- src/auth/token.py tests/auth/test_token.py
```

同一文件包含多个职责时使用：

```bash
git add -p -- src/auth/token.py
```

除非已经确认全部改动只有一个职责，否则禁止使用：

```bash
git add .
git add -A
git add --all
```

不得覆盖或撤销用户此前已经暂存的内容。发现暂存区包含无关改动时，先说明情况，再采用不会丢失改动的方式重新划分。

### 第五步：检查暂存内容

每次提交前必须运行：

```bash
git diff --cached --stat
git diff --cached --check
git diff --cached
```

逐项确认：

* 暂存区只包含当前候选提交
* 所有文件和 hunk 都服务于同一职责
* 没有调试代码、临时文件或意外格式化
* 提交主题可以覆盖全部暂存内容
* 没有遗漏该行为不可缺少的改动

### 第六步：验证行为

运行提交计划中对应的验证命令。

验证应与风险相匹配，例如：

```bash
pytest tests/auth/test_token.py
npm test -- search
python -m compileall src/auth
docker compose config
bash -n scripts/deploy.sh
```

如果无法运行验证：

1. 明确说明无法验证的原因；
2. 说明已经完成的替代检查；
3. 不得声称测试通过或功能正常。

### 第七步：提交

仅在用户授权提交时执行：

```bash
git commit -m "fix(auth): refresh expired access tokens"
```

提交后检查：

```bash
git show --stat --oneline HEAD
git status --short
```

然后处理下一个候选提交，重复暂存、验证和提交流程。

## 职责拆分规则

### 默认应该拆分

出现以下任一情况时，默认拆分：

* 不同部分可以独立回滚
* 主题需要列举多个独立动作
* 配置、迁移、业务逻辑、接口或文档具有独立价值
* 同一文件包含无关 hunk
* 纯重构与行为变更混在一起
* 多个测试验证不同的行为
* 发布流程中包含不同阶段的操作

涉及发布脚本时，至少分别判断以下职责：

* 构建镜像或制品
* 离线部署或首次安装
* 热更新或版本切换
* 回滚
* 模型转换或导出

这些职责即使服务于同一次发布，也默认是不同候选提交。

### 可以合并

只有满足以下条件之一时才能合并：

* 多个文件缺一不可，拆开后无法构建或无法表达完整行为
* 实现和最小回归测试按仓库惯例属于同一原子改动
* 纯机械重命名必须同步修改所有引用
* 拆开后中间提交会处于不可运行或语义不完整状态

“属于同一功能”“位于同一目录”“使用同一 scope”不是合并理由。

测试是否和实现放在同一提交，优先遵循仓库惯例；没有明确惯例时，根据是否能够独立验证和回滚判断。

## 提交消息

没有仓库规范时，默认采用 Conventional Commits：

```text
<type>[(<scope>)][!]: <subject>

[可选正文]

[可选页脚]
```

规则：

* `type` 必填
* `scope` 可选，使用稳定且简洁的模块名称
* `!` 表示破坏性变更
* `subject` 使用祈使语气，描述结果而不是操作过程
* 主题末尾不加句号
* 正文解释原因、背景和重要影响，不重复 diff
* 破坏性变更使用 `BREAKING CHANGE:` 页脚

默认 type：

| type       | 使用场景              |
| ---------- | ----------------- |
| `feat`     | 新增用户可见功能或能力       |
| `fix`      | 修复缺陷、异常或回归        |
| `docs`     | 仅修改文档             |
| `style`    | 仅修改格式、空白或不影响行为的样式 |
| `refactor` | 调整结构但不改变外部行为      |
| `perf`     | 性能优化              |
| `test`     | 新增或修改测试           |
| `build`    | 构建系统或外部依赖         |
| `ci`       | 持续集成配置或脚本         |
| `chore`    | 不改变产品行为的维护工作      |
| `revert`   | 回滚已有提交            |

`update`、`deps` 等非标准 type 只有仓库明确允许时才能使用。

好的示例：

```text
feat(search): add exact phrase matching
fix(auth): reject expired refresh tokens
docs(api): document pagination limits
refactor(cache): isolate eviction policy
```

避免：

```text
update files
fix bug
misc changes
feat(core): add cache and update docs
```

未经用户要求或仓库明确规定，不添加：

* `Co-Authored-By`
* AI 或生成工具署名
* 额外身份页脚

## 历史改写

修改已有提交前必须确认：

* 目标提交由当前任务创建，或用户明确授权修改
* 提交尚未推送，或用户明确授权改写远端历史
* 工作区和暂存区改动已经安全保留
* 当前分支不是多人共享或受保护分支

不得擅自改写：

* 他人创建的提交
* 已共享分支历史
* 已发布版本
* 用户未授权修改的远端提交

提交已经推送时，必须先说明强制推送可能覆盖他人工作的风险。

## 最终检查

全部提交完成后运行：

```bash
git status --short --branch
git log --oneline -10
```

逐个检查本次创建的提交：

```bash
git show --stat --oneline <commit>
```

确认：

* 每个提交只有一个职责
* 每个提交可以独立审查、验证和回滚
* type、scope、语言和长度符合仓库规则
* 提交消息覆盖全部改动
* 没有意外文件或无关 hunk
* 没有未经允许的署名
* 剩余工作区改动符合预期

工作区干净只能证明文件已经被处理，不能证明提交拆分正确。

## 红色信号

出现以下想法时，停止暂存并重新检查职责：

| 想法              | 实际问题                |
| --------------- | ------------------- |
| “这些都属于同一个功能”    | 一个功能可能包含多个可独立回滚的行为  |
| “这些文件都在同一目录”    | 目录结构不等于职责边界         |
| “它们使用同一个 scope” | scope 不能代替原子性判断     |
| “用户说提交全部改动”     | 用户授权的是处理范围，不是合并方式   |
| “先全部暂存再检查”      | 容易混入无关文件，应该逐个候选提交暂存 |
| “测试最后统一运行就行”    | 每个提交必须有与其职责对应的验证    |
| “工作区已经干净”       | 干净不能证明提交边界正确        |
| “文档和配置顺手一起提交”   | 它们可能具有独立审查和回滚价值     |
| “拆得太细不好看”       | 判断标准是职责完整性，不是提交数量   |

## 自动化相关请求

用户询问以下内容时：

* commitlint
* Husky
* Commitizen
* lint-staged
* 语义发布
* CI 提交消息校验

**REQUIRED REFERENCE：读取 `references/automation.md`。**

