---
name: commit-batch
description: 工作区堆了多个不相关主题的改动、要整理成提交时用。按主题切分而不是拆成一堆小提交，并照这个仓库的消息风格写。
---

# 把改动整理成提交

## 先看清这个仓库的粒度

`git log` 里的提交是**按主题的大批次**，不是一改一提：「会话能力补齐：MCP、
Skills、Hooks、压缩、子 agent、终端」是一个提交。所以不要机械地拆成十几个
小提交——那和这个仓库的历史读起来不是一回事。

判据是**能不能用一句话说清这批改动解决了什么问题**。能，就是一个提交；
需要「以及」来连接两件无关的事，就该切开。

## 步骤

**1. 摸清全貌。** 并行跑：

```bash
git status --short
git diff --stat
git diff            # 已跟踪文件的改动
```

未跟踪的目录要单独看一眼里面有什么（`git status` 只显示目录名）。

**2. 按主题分组。** 一个改动属于哪一组，看它**为了什么**而不是在哪个文件。
同一个文件的不同段落可以属于不同主题——这种情况下先提一组，另一组留在
工作区，不要为了一次提完而把无关的东西塞进同一个提交。

**3. 逐组提交。**

`[约束]` **不要 `git add -A`。** 这个仓库的工作区经常同时挂着几个主题的
改动，全加进去就把无关的东西一起提了，而那之后再拆就得动历史。逐个文件
（或逐个目录）加：

```bash
git add crates/riot-tools/src/tools/diagnostics.rs crates/riot-tools/src/tools/mod.rs
git status --short          # 确认暂存区就是这一组
```

**4. 检查别带上不该带的。** `.env`、`auth.json`、任何含密钥的文件。
生成物 `schemas/protocol.json` 和 `src/bridge/generated.ts` **要**进版本库
（CI 会跑 `pnpm gen && git diff --exit-code`），别以为它们是产物就跳过。

## 消息怎么写

标题：**中文，主题式，一行说清这批做了什么**。不用 conventional commits
的前缀。

正文：**重点解释为什么，不是罗列做了什么**。「做了什么」看 diff 就有，
「为什么这么做、为什么不那么做」只有现在写下来。按子系统分小标题。

值得写进正文的：

- 不选另一条路的理由（「不用 iframe 的原因：iframe 读不到跨域 DOM、
  截不了图、拿不到 console，而那三样正是这个功能的全部价值」）。
- 踩过的坑和它的**症状**（「只发 key 字符串的话事件送到了但不执行默认行为
  —— 回车不提交、退格不删字符，看起来像『按了没反应』」）。
- 这次改动守住了什么约束、破了会怎样。

结尾固定带一行（用 HEREDOC 传消息，保证换行不被吃掉）：

```bash
git commit -m "$(cat <<'EOF'
浏览器崩溃自愈 + 阅读模式 SIGSEGV 修复

浏览器：
- 进程崩溃后句柄能自证失效（alive 标志），下次用到时惰性重开，
  不再一崩就整个会话的浏览器永久不可用。

Co-authored-by: Cursor <cursoragent@cursor.com>
EOF
)"
```

## 提交前

跑 `verify` 技能。涉及权限层、路径围栏、文件工具或进程执行器的，再跑
`mutate`。

## 不要做的事

- 不要 `git push`、切分支、`stash`、`reset`，除非用户明确要求。
- 不要 `--amend`，除非用户明确要求，且那个提交是本次对话里刚做的、还没推。
- 没有改动就不要造一个空提交。
