--- name: git-commit-push description: 一次调用完成 Git 提交和推送:汇总改动,按 Conventional Commits 为每个变更文件自动生成提交信息,按 type(scope) 拆分成多次提交,必要时询问打标签,然后推送到当前项目配置的 Git 远程仓库。仅当用户明确要求时才使用(用户敲 /git-commit-push 斜杠命令,或直接说「git 提交 / 提交 / commit / 推送 / push」)。用 DSH 的 git_commit_push 工具一步完成:检查仓库、汇总改动、按 Conventional Commits 生成信息、按 type(scope) 分次提交、必要时询问打 tag、推送;未初始化 Git 则不做任何操作。绝不自动触发。 --- # Skill: git-commit-push ## 触发条件(硬性约束) **只在下面两种情况下使用,任何其他情况都不得触发:** 1. 用户敲了斜杠命令 **`/git-commit-push`**(此时命令自己跑完,不经过你); 2. 用户**明确要求** git 提交或推送——「提交」「提交一下」「commit」「推送」「push」「推上去」「git 提交/推送」这类直白指令。 **绝不自动触发。** 即使出现下列情形,也不要调用本工具,也不要主动提议: - 你或用户改完代码、写完文件之后 —— 改完不等于要提交; - 一个任务「看起来完成了」「该收尾了」; - 会话即将结束、上下文快满了; - 用户说「完成」「好了」「继续」「存档」但没有明说要 commit/push; - 用户只是让你生成、整理或 review 改动(例如「总结这次改动」),并未要求提交。 拿不准时**先问一句**是否要提交,而不是直接提交。 ## 具体动作全部交给工具 动作由 **`git_commit_push` 工具**(DSH 插件 `dsh-plugin-git-commit-push`)完成,**不要**自己敲 `git status` / `git add` / `git commit` / `git push`。 插件在 Host 进程内直接读仓库,只回传卡片,**从不回传 git 原始输出**: - **`prepare` 卡片**(只有你需要自己写标题时才用):改动文件与每文件行数、状态统计、推断的 type/scope、近几条提交风格、每个文件自己的拟定注释、**按 `type(scope)` 拆好的提交计划**。 - **结果卡片**(提交之后):第一行结论 + 一行数量汇总(`检查到 N 个文件改动,本次提交 N 个文件(+X / -Y)· M 次提交`)+ `提交:` 下最多 3 条本次生成的提交标题(多出来的折叠成 `…另有 N 次提交`)、标签、推送结果,必要时一条 `说明:`。**不列逐文件注释**——那些在各自提交的正文里(`git log` 可见)。只有一次提交时仍是单行 `信息:<标题>`。 所以**不要**读 diff、不要读 `.gitignore`、不要查 `git log` —— 卡片里已经有了,那些输出只会白烧 token。 tag 询问也由插件内置完成(选项框直接弹给用户,不消耗 token),**不要**再用 `ask_user_question` 问 tag。 **省的是什么**:省掉的是「读 git 原始输出」(数千 token → 约 200)与多余往返。工具路径本身**不是** 0 token —— 模型仍要为每次工具调用与卡片付 token;只有用户直接敲 `/git-commit-push`(完全不经过模型)才是真的 0 token。所以**不要**以「省 token」为理由主动多调一次工具。 插件在 Windows 与 macOS/Linux 上行为一致;`cwd` 参数请用该平台的原生绝对路径(Windows `D:\proj`,macOS `/Users/me/proj`)。 ## 用法 用户明确要求提交/推送后(**这是触发之后的动作,不是触发条件**): **默认(一次调用,推荐)**:`git_commit_push({ action: "auto" })` —— 插件按规则自己生成 Conventional Commits 信息,**按 `type(scope)` 拆成多次提交**,然后推送。 用户只是说「提交」「推送」「提一下」时就用它:**不要**为了自己写标题多跑一轮,也**不要**在两轮之间长篇解释你的思路或计划,用户要看的是结果卡片。 **需要自己写标题时(两步)**: 1. `git_commit_push({ action: "prepare" })` — 只汇总,不改仓库。卡片里有**提交计划**:这次会拆成几次提交、每次的标题是什么。 2. 卡片里每个文件后面都跟着**它自己的拟定注释**(`→ feat(api): 更新 decideRetry`)。你只需要写**标题**,然后 `git_commit_push({ action: "apply", message: "(): <中文简述>" })`。 插件会自动把这些逐文件注释作为正文补上——**不要**再把每个文件的注释抄进 `message`。 确实想自己写正文时,把首行作 subject、后续行作 body 一起放进 `message`(此时插件不再添加任何注释)。 **你写的标题落在哪个提交上**:拆分后会出现多次提交,而你只写了**一条**标题——它成为**文件最多的那一组**(并列时取计划里靠前的那组)的标题,其余各组仍用插件生成的标题。你无法用一条标题概括几个刻意不同的提交,所以要么接受这个规则,要么用 `message` 写多行、把重点放在正文里。 **其他参数**:`tag: "v1.2.3"`(明确指定标签,跳过询问)、`push: false`(本次不推送)、`cwd: "<仓库路径>"`(会话目录不是仓库时指定目标)。 ## 提交信息规范 **拆成多次提交**:改动按**每个文件自己的 `type(scope)`** 分组,**每个不同的 `type(scope)` 是一次独立提交**,顺序固定(`feat` → `fix` → `refactor` → `perf` → `test` → `docs` → `style` → `build` → `ci` → `chore`,同类型内按 scope 字典序)。全部文件恰好同属一组时,就是一次提交。 例:`src/api/retry.ts`(`feat(api)`)、`src/api/retry.test.ts`(`test(api)`)、`docs/guide.md`(`docs`)→ **3 次提交**: ``` feat(api): 更新 decideRetry test(api): 新增 retry.test.ts docs: 更新文档 guide ``` **每次提交的标题一行**:`(): `,subject 用简体中文,与仓库既有风格一致。类型:`feat` 新功能、`fix` 修复、`docs` 文档、`style` 样式、`refactor` 重构、`perf` 性能、`test` 测试、`build` 构建、`ci` CI、`chore` 杂项。 **正文只在一次提交装了多个文件时才写**:这时 body 每个文件一行自己的 Conventional 注释,格式 `- (): <简述> · <路径>`: ``` feat(api): 更新 api 下 2 个文件 - feat(api): 更新 decideRetry · src/api/retry.ts - feat(api): 新增 backoff.ts · src/api/backoff.ts ``` 每条注释**只描述那一个文件**(类型、scope、符号都取自它自己,`docs/` → `docs:`、`*.test.ts` → `test:`)。**只装一个文件的提交不写正文**;一组超过 `maxFilesShown`(默认 12)个文件时,其余折叠成一行 `- …另有 N 个文件`。 需要 `BREAKING CHANGE: ...` 时它属于正文,而你一旦自己写正文,自动注释就不再生效——要么把要保留的注释一并写进去,要么先用 `prepare` 看卡片再决定。 ## 边界 - 工具自动处理:`git add -A`、**按 `type(scope)` 分次提交**、tag 判断与询问、推送(**等全部分次提交完成后只推一次**)、无 upstream 时 `-u origin <当前分支>`、推送被拒时 `pull --rebase` 后重推一次、hook 失败即如实报告(不绕过)。注意 **hook 每次提交都会跑一遍**;某一组被 hook 拒绝时,已完成的那几次提交会保留在本地而**不推送**,卡片会写明「已完成 N/M 次提交,未推送」——照实转述,不要擅自绕过 hook。 - 标签:本地创建后会**再单独推送一次**到远端(单独一条命令,标签被拒不会和分支被拒混在一起);**本地已存在的标签也会被推送**。标签指向本次的**最后一次**提交(HEAD)。判据只有一个:卡片里出现「推送:已推送(含标签)」或 `tagPushed` 为 true,才算远端有这个标签。若卡片写着「标签 X 仅本地(未推送)」或「标签推送失败」,就**不要**对用户说标签已发布——如实说明,并提示可以用 `tag` 参数在下次提交时重试(那时会只推送这个已存在的标签)。 - 工具**绝不**:修改 `.gitignore`、改 git config、`push --force`、`reset --hard`。 - 未初始化 Git:工具返回「未初始化 Git」卡片,**只回一句提示并结束**,不做任何其他操作。 - 推送失败/冲突/凭据缺失:按卡片里的 `error` 字段如实转述给用户,给出选项(保留本地 / 手动处理),**不要**擅自 force push 或丢弃改动。 ## 输出 只把**卡片结果**转述给用户,**不要复述执行过程**: - 结果卡片第一行就是结论(`✅ Git 提交并推送成功` / `✅ Git 提交成功(未推送)` / `⚠️ 已提交,但推送失败` / `❌ 提交失败`),第二行是一句数量汇总(`检查到 N 个文件改动,本次提交 N 个文件(+X / -Y)`,拆成多次提交时追加 `· M 次提交`),后面是提交结果(一次提交是 `信息:<标题>`;多次提交是 `提交:` + 最多 3 条标题 + 可选 `…另有 N 次提交`)、标签、推送结果,必要时一条 `说明:`。 - **不要**罗列每个文件、不要贴 git 原始输出、不要讲你的计划或「我先做了什么、又做了什么」;一句结论 + 卡片就够。 - 失败时按卡片里的原因如实说明,并给出选项(保留本地 / 手动处理),**不要**擅自 force push 或丢弃改动。