关于 commit-push-pr
为 Agent 提供提交更改、推送到 GitHub 并创建或更新 PR 的流程指引,涵盖分支处理、质量检查及错误应对,并要求遵守 Conventional Commits 和提交钩子。
主要功能
- 01检查 Git 状态与分支
- 02生成 Conventional Commits 消息
- 03检查暂存更改中的问题
- 04推送分支并处理 PR
适用场景
- 01提交本地更改并创建 PR
- 02将未推送的提交推送到现有 PR
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ llama-farm/ llamafarm --skill commit-push-pr安装后在 Claude Code 中输入/commit-push-pr确认已加载。
详细介绍
提交、推送与 PR 技能
自动执行 Git 工作流:提交更改、推送到 GitHub,并妥善处理各种边缘情况后创建 PR。
必读内容
执行前,请熟悉 Git 工作流规范: @.claude/rules/git_workflow.md
关键规则:
- 使用 Conventional Commits 格式:
type(scope): description - 绝不在提交或 PR 中提及 Claude(不得添加共同作者或提及)
- 绝不跳过提交前钩子(不得使用
--no-verify)
执行工作流
步骤 1:检查 Git 状态
运行以下命令以了解当前状态:
# Detect the default branch (main, master, etc.)
DEFAULT_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@')
# Fallback if symbolic-ref fails (e.g., shallow clone or missing HEAD)
if [ -z "$DEFAULT_BRANCH" ]; then
DEFAULT_BRANCH=$(git remote show origin 2>/dev/null | grep 'HEAD branch' | awk '{print $NF}')
fi
# Final fallback to 'main' if detection fails
DEFAULT_BRANCH=${DEFAULT_BRANCH:-main}
# Get current branch
BRANCH=$(git branch --show-current)
# Check for uncommitted changes
git status --porcelain
# Check for unpushed commits (if branch has upstream)
git log origin/$DEFAULT_BRANCH..HEAD --oneline 2>/dev/null || echo "No upstream or no commits ahead"
# Check if branch has upstream tracking
git rev-parse --abbrev-ref @{upstream} 2>/dev/null || echo "No upstream"
确定以下状态:
HAS_CHANGES:是否有未提交的更改(已暂存、未暂存或未跟踪)?HAS_UNPUSHED:是否有领先于 origin/$DEFAULT_BRANCH 的提交?ON_DEFAULT_BRANCH:当前分支是否为默认分支($DEFAULT_BRANCH)?HAS_UPSTREAM:该分支是否跟踪某个远程分支?
步骤 2:处理“无事可做”的情况
如果 !HAS_CHANGES && !HAS_UNPUSHED:
Inform user: "No changes to commit and no unpushed commits. Nothing to do."
Exit gracefully.
步骤 3:处理“没有更改,但有未推送提交”的情况
如果 !HAS_CHANGES && HAS_UNPUSHED:
- 检查 PR 是否已存在:
gh pr list --head "$(git branch --show-current)" --json number,url,title
-
如果 PR 已存在:
- 询问是否要将更新推送到现有 PR
- 报告 PR URL
-
如果没有 PR:
- 询问是否要推送并创建新 PR
- 继续执行步骤 7
步骤 4:分支管理(如果 HAS_CHANGES)
如果当前位于默认分支($DEFAULT_BRANCH):
- 告知用户需要将更改放到功能分支上
- 先暂存更改,以便分析:
git add -A
git diff --staged --stat
-
根据更改生成 Conventional Commits 格式的提交消息(参见步骤 5)
-
从提交消息派生分支名称:
feat(cli): add project list→feat-cli-add-project-listfix: resolve memory leak→fix-resolve-memory-leak- 规则:全部小写,将空格和特殊字符替换为连字符,最多 50 个字符
-
创建并切换到新分支:
git checkout -b <branch-name>
如果当前已位于功能分支:
- 继续使用现有分支
- 检查是否存在 PR,以便了解上下文
步骤 5:暂存更改并生成提交消息
- 暂存所有更改:
git add -A
- 分析已暂存的更改:
git diff --staged --stat
git diff --staged
-
根据以下信息生成 Conventional Commits 格式的提交消息:
- 更改的文件(根据目录推断范围)
- 更改性质(feat/fix/refactor/docs/test/chore)
- 总结“为什么”更改,而不只是“改了什么”
-
向用户展示提交消息。格式示例:
Proposed commit message:
feat(cli): add project listing command
Adds a new 'lf project list' command that displays all projects
in the current workspace with their status.
Do you want to use this message, modify it, or provide your own?
步骤 5.5:质量检查
跳过条件:传入了 --quick 标志。
提交前,对已暂存的更改进行质量检查。
1. 自动修复简单问题(无需询问)
搜索并移除调试语句:
# Find files with debug statements
git diff --staged --name-only | xargs grep -l -E "(console\.(log|debug|info)|debugger|print\()" 2>/dev/null
对找到的每个文件:
- 移除
console.log(...)、console.debug(...)、console.info(...)语句 - 移除
debugger;语句 - 移除
print(...)语句(Python) - 修复后重新暂存文件
报告:“已自动修复:从 M 个文件中移除 N 条调试语句”
2. 检查需要处理的问题
扫描已暂存的差异,查找以下问题:
| 问题 | 严重程度 | 操作 |
|---|---|---|
| 硬编码的机密信息(API 密钥、密码) | 阻止 | 无法自动修复,用户必须移除 |
命令注入(shell=True、os.system) | 阻止 | 无法自动修复,用户必须重构 |
| 空的 catch/except 代码块 | 建议 | 建议添加错误日志记录 |
| 重复代码模式 | 建议 | 建议提取代码 |
| 未使用的导入 | 建议 | 建议移除 |
| TODO/FIXME 注释 | 警告 | 提醒用户,但允许继续 |
3. 处理阻止项
如果发现阻止项:
- 列出每项问题,并标明文件:行号
- 停止工作流
- 用户必须手动修复后重新运行
4. 处理可建议的修复
针对每项建议修复:
- 显示:文件、行号、问题、建议的修复方式
- 询问:“应用此修复?(y/n/all/skip)”
- 如果用户同意:应用修改并重新暂存
- 如果用户跳过:不进行修复,继续执行
5. 处理警告
对于警告项:
- 显示摘要
- 继续执行,不阻止工作流
第 6 步:创建提交
使用已批准的提交信息创建提交:
git commit -m "$(cat <<'EOF'
type(scope): short description
Optional longer description explaining the change.
EOF
)"
重要:
- 多行信息请使用 HEREDOC
- 切勿添加共同作者或 Claude 署名
- 让 pre-commit 钩子运行(切勿使用
--no-verify)
如果提交因 pre-commit 钩子而失败:
- 向用户报告失败
- 显示钩子输出
- 切勿使用
--no-verify重试 - 询问用户如何继续(修复问题或中止)
第 7 步:推送到远程
- 检查分支是否有关联的上游分支:
git rev-parse --abbrev-ref @{upstream} 2>/dev/null
- 如果没有上游分支,使用
-u推送:
git push -u origin $(git branch --show-current)
- 如果有关联的上游分支,常规推送:
git push
如果推送因冲突而失败:
- 告知用户发生了冲突
- 建议使用:
git pull --rebase origin $DEFAULT_BRANCH或git merge origin/$DEFAULT_BRANCH - 切勿强制推送
第 8 步:创建或报告 PR
- 检查 PR 是否已存在:
gh pr list --head "$(git branch --show-current)" --json number,url,title
-
如果 PR 已存在:
- 报告:"更改已推送到现有 PR:"
- 显示 PR 标题和编号
-
如果没有 PR:
- 根据提交信息生成 PR 标题(第一行)
- 生成 PR 正文,概述更改内容
- 创建 PR:
gh pr create --title "type(scope): description" --body "$(cat <<'EOF'
## Summary
- Brief description of changes
## Changes
- List of key changes made
## Test Plan
- How to verify these changes work
EOF
)"
- 向用户报告新 PR 的 URL
分支名称生成
将提交信息转换为有效的分支名称:
| 输入 | 输出 |
|---|---|
feat(cli): add project list command | feat-cli-add-project-list-command |
fix: resolve memory leak in cache | fix-resolve-memory-leak-in-cache |
refactor(server): simplify auth flow | refactor-server-simplify-auth-flow |
算法:
- 取提交信息(仅第一行)
- 将所有内容转换为小写
- 移除类型/范围后的冒号
- 将
(和)替换为- - 将空格和特殊字符替换为
- - 将多个连续连字符合并为一个
- 在单词边界处截断,最多保留 50 个字符
- 移除末尾的连字符
错误处理
| 错误 | 操作 |
|---|---|
| Pre-commit 钩子失败 | 显示输出,询问用户是否修复,切勿绕过 |
| 推送被拒绝(冲突) | 建议变基/合并,切勿强制推送 |
| 创建 PR 失败 | 显示错误,建议手动创建 |
| 当前目录不是 git 仓库 | 告知用户并退出 |
| 未安装 gh CLI | 告知用户如何安装 |
| 未通过 GitHub 身份验证 | 建议使用 gh auth login |
输出格式
成功时,报告:
Committed: feat(cli): add project list command
Branch: feat-cli-add-project-list-command
Pushed to: origin/feat-cli-add-project-list-command
PR: https://github.com/owner/repo/pull/123
给 Agent 的说明
- 切勿提及 Claude——不添加共同作者行,PR 描述中不写“由 Claude 生成”
- 遵守钩子——pre-commit 钩子有其用途,切勿跳过
- 提供清晰信息——告知用户每个步骤的进展
- 妥善处理错误——不要让仓库处于损坏状态
- 不确定时先询问——如果提交信息不明确,请询问用户
- 保持简单——每次调用只创建一个提交,采用清晰的线性工作流
评论
支持 Markdown