关于 git-commit-workflow
Git Commit Workflow 是为 Git 仓库提供提交规范与暂存流程指导的技能,适用于需要规划清晰、聚焦提交的开发者。它涵盖 Conventional Commits、逐文件暂存、变更分组和提交前上下文收集;实际创建提交由其他技能处理。
主要功能
- 01Conventional Commits 格式指导
- 02逐文件显式暂存
- 03将变更归为聚焦提交
- 04提交前收集仓库上下文
- 05指导提交信息与 issue 引用
适用场景
- 01为代码库制定提交信息格式
- 02将多项修改拆分为逻辑提交
- 03批量变更时规划按目录提交
- 04提交前查看状态与差异摘要
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ laurigates/ claude-plugins --skill git-commit-workflow安装后在 Claude Code 中输入/git-commit-workflow确认已加载。
附带文件REFERENCE.mdscripts/commit-context.sh
详细介绍
Git 提交工作流
何时使用此技能
| 在以下情况使用此技能…… | 在以下情况使用替代方案…… |
|---|---|
| 为仓库设计 conventional commit 消息和暂存约定 | 使用 git-commit 实际创建提交(它会处理 pre-commit 钩子和问题检测) |
| 审查如何将更改按逻辑归组为重点明确的提交 | 使用 git-commit-trailers 了解 BREAKING CHANGE / Co-authored-by 页脚规则 |
| 讨论谦逊、基于事实的提交沟通风格 | 使用 github-issue-autodetect 在消息中添加 Fixes #N / Closes #N 链接 |
为代码库编写 feat(scope): subject 规则 | 使用 github-pr-title 将相同的 conventional 格式应用于 PR 标题 |
使用 conventional commit 和显式暂存工作流,提供关于提交消息约定、暂存实践和提交最佳实践的专业指导。
如需详细示例、高级模式和最佳实践,请参阅 REFERENCE.md。
前提条件
暂存任何文件之前——尤其是在涉及多个子目录的大批量编辑或提交循环工作流中——请确认工作区只有你自己的更改:
| 检查 | 原因 | 方法 |
|---|---|---|
| 协作者检查 | 同一检出目录中的另一个 Claude 会话可能已经预先暂存了文件(重试 git commit -a、暂存后放弃),导致你的循环将这些文件错误地纳入提交。请在开始时执行此检查,不要临时检查。 | SlashCommand → /git:coworker-check |
| 确认工作区范围 | 确认 git status --porcelain 仅显示你的修改 | git status --porcelain |
如果 /git:coworker-check 返回的结果不是 clear,请停止操作,改用新的工作树(git worktree add ../<repo>-<task>),或在继续之前询问用户。四种检测信号请参阅 .claude/rules/agent-coworker-detection.md。
核心专长
- Conventional Commits:用于自动化和提高清晰度的标准化格式
- 显式暂存:始终逐个暂存文件,确保清晰可见
- 逻辑分组:将相关更改归组为重点明确的提交
- 沟通风格:谦逊、基于事实、简洁的提交消息
- Pre-commit 集成:提交前运行检查
**注意:**提交会在 main 分支上创建,并推送到用于 PR 的远程功能分支。有关 main 分支开发模式,请参阅 git-branch-pr-workflow 技能。
Conventional Commit 格式
标准格式
type(scope): description
[optional body]
[optional footer(s)]
有关页脚/尾注模式(Co-authored-by、BREAKING CHANGE、Release-As),请参阅 git-commit-trailers 技能。
提交类型
- feat:面向用户的新功能
- fix:面向用户的错误修复
- docs:文档更改
- style:格式调整、缺少分号等(不更改代码)
- refactor:重构代码,不改变行为
- test:添加或更新测试
- chore:维护任务、依赖项更新、linter 修复
- perf:性能改进
- ci:CI/CD 更改
示例
# Feature with scope
git commit -m "feat(auth): implement OAuth2 integration"
# Bug fix with body
git commit -m "fix(api): resolve null pointer in user service
Fixed race condition where user object could be null during
concurrent authentication requests."
# Breaking change
git commit -m "feat(api)!: migrate to GraphQL endpoints
BREAKING CHANGE: REST endpoints removed in favor of GraphQL.
See migration guide at docs/migration.md"
提交消息最佳实践
应该:
- 使用祈使语气(“add feature”,而不是“added feature”)
- 将首行控制在 72 个字符以内
- 简洁、客观地描述
- 始终引用相关问题——每个提交都应关联相关问题
- 使用 GitHub 关闭关键词:
Fixes #123、Closes #456、Resolves #789 - 类型和范围使用小写
- 保持谦逊、低调
不应该:
- 使用过去时(“added”或“fixed”)
- 在主题行中包含不必要的细节
- 使用含糊的描述(“update stuff”“fix bug”)
- 省略问题引用——始终将提交与其上下文关联
- 仅想引用时使用关闭关键词(
Fixes),此时应使用Refs
提交前收集上下文(推荐)
提交之前,用一条命令收集所有上下文:
# Basic context: status, staged files, diff stats, recent log
bash "${CLAUDE_PLUGIN_ROOT}/skills/git-commit-workflow/scripts/commit-context.sh"
# With issue matching: also fetches open GitHub issues for auto-linking
bash "${CLAUDE_PLUGIN_ROOT}/skills/git-commit-workflow/scripts/commit-context.sh" --with-issues
脚本会输出:分支信息、暂存/未暂存状态、差异统计、检测到的作用域、近期提交风格、提交前配置状态,以及可选的未解决问题。使用此输出编写提交消息。详情请参阅 scripts/commit-context.sh。
显式暂存工作流
始终逐个暂存文件
# Show current status
git status --porcelain
# Stage files one by one for visibility
git add src/auth/login.ts
git add src/auth/oauth.ts
git status # Verify what's staged
# Show what will be committed
git diff --cached --stat
git diff --cached # Review actual changes
# Commit with conventional message
git commit -m "feat(auth): add OAuth2 support"
批量编辑 / 按插件执行提交循环
当单个更改涉及许多子目录(按插件、按软件包或按文档),且每个目录都需要单独的作用域提交以供 release-please 使用时,应编写一次性脚本,而不是直接串联命令。
为什么内联循环会失败
| 模式 | 阻止原因 |
|---|---|
for d in a b c; do git add "$d/" && git commit -m "..."; done | bash-antipatterns.sh 会阻止 git add ... && git commit ...——串联会修改索引的 git 命令可能引发 index.lock 竞态条件 |
git add -A、git add --all、git add . | bash-antipatterns.sh 会阻止广泛暂存——可能会一并纳入 .env、大型二进制文件,以及共享检出目录中任何同事会话正在处理的文件(参见 .claude/rules/agent-coworker-detection.md) |
在每个插件对应的独立 Bash 工具调用中重复执行 git add <paths>; git commit -m "..." | 虽然可行,但对 40 个插件执行时,约 3 次工具调用 × N 个插件会产生数百次往返调用 |
标准做法
将循环写入 /tmp/commit-loop-<slug>.sh,然后在一次 Bash 调用中运行。钩子会将该文件视为脚本,而不是命令链——会修改索引的命令会在 bash 中依次执行,不会通过单独的工具调用产生竞态。
#!/bin/bash
# /tmp/commit-loop-trim-descriptions.sh
set -uo pipefail
cd "$REPO_ROOT" || exit 1
for p in plugin-a plugin-b plugin-c; do
# Skip plugins with nothing staged or modified inside them
[ -z "$(git status --porcelain "$p/")" ] && continue
git add "$p/skills/" # explicit path, never -A or .
git commit -m "docs($p): trim skill descriptions for listing budget"
done
调用一次:
bash /tmp/commit-loop-trim-descriptions.sh
每次迭代都会运行提交前钩子,并生成一个干净的按插件划分的提交。在脚本内的 git add 和 git commit 之间使用 ; 或换行符(不要使用 &&)。
失败恢复
如果循环中途终止(在第 K 个插件上提交前钩子失败),第 1 到 K-1 个插件的提交已经完成——不会回滚。恢复规则如下:
| 情况 | 操作 |
|---|---|
| 提交前钩子发现了插件 K 中的实际问题 | 修复问题后重新运行脚本——[ -z ... ] && continue 防护条件会跳过没有剩余更改的插件 |
| 重新运行脚本时拾取了插件 K 遗留的暂存路径 | 这是预期行为——通过 git status --porcelain "$p/" 进行的未暂存或已暂存检查会捕获两者 |
| 想跳过插件 K 并继续 | 编辑脚本,从列表中移除插件 K,然后重新运行 |
不要重新暂存已经干净提交的路径;git status 是判断剩余内容的依据。
使用 HEREDOC 编写多行消息,不要从临时文件中读取。
git commit -m "$(cat <<'EOF'
feat(auth): add OAuth2 support
Implements token refresh and secure storage.
Fixes #123
EOF
)"
也可以通过路径传递消息——git commit -F <file> /
--file=<file> 是 git 中与 gh --body-file 对应的选项,且
bash-antipatterns 钩子对此有豁免(#2462):
git commit -F /tmp/commit-msg.txt
钩子仍会避免的是这种绕远路的折中做法:先写入临时文件,再通过 -m "$(cat /tmp/commit-msg.txt)" 将内容读回。要么使用 heredoc 内联编写消息,要么通过路径传递文件。
沟通风格
谦逊、基于事实的消息
# Good: Concise, factual, modest
git commit -m "fix(auth): handle edge case in token refresh"
git commit -m "feat(api): add pagination support
Implements cursor-based pagination for list endpoints.
Includes tests and documentation."
聚焦事实:更改了什么、为何更改(如果原因不明显),以及影响(是否存在破坏性更改)。
问题引用摘要
| 场景 | 模式 | 示例 |
|---|---|---|
| 修复问题的错误修复 | Fixes #N | Fixes #123 |
| 完成问题的功能 | Closes #N | Closes #456 |
| 相关但未解决问题 | Refs #N | Refs #789 |
| 跨仓库 | Fixes owner/repo#N | Fixes org/lib#42 |
| 多个问题 | 重复关键词 | Fixes #1, fixes #2 |
最佳实践
提交频率
- 尽早且频繁地提交:小而聚焦的提交
- 每次提交只包含一个逻辑更改:更易于审查和还原
- 保持提交原子性:每次提交都应是完整且可工作的状态
提交消息长度
# Subject line: <= 72 characters
feat(auth): add OAuth2 support
# Body: <= 72 characters per line (wrap)
# Use blank line between subject and body
Agentic 优化
| 上下文 | 命令 |
|---|---|
| 提交前上下文 | bash "${CLAUDE_PLUGIN_ROOT}/skills/git-commit-workflow/scripts/commit-context.sh" |
| 上下文 + 问题 | bash "${CLAUDE_PLUGIN_ROOT}/skills/git-commit-workflow/scripts/commit-context.sh" --with-issues |
| 快速状态 | git status --porcelain |
| 暂存区差异统计 | git diff --cached --stat |
| 最近提交风格 | git log --format='%s' -5 |
| 可关联的未关闭问题 | gh issue list --state open --json number,title --limit 30 |