关于 create-pr
用于将当前工作创建为 GitHub Pull Request 的技能,涵盖分支和提交准备、远程仓库检测及 PR 内容生成。它可处理 Fork 工作流并检查仓库中的 PR 模板。
主要功能
- 01检测仓库远程地址和 Fork 关系
- 02需要时创建功能分支
- 03暂存并提交预期更改
- 04变基到上游默认分支
- 05根据更改生成 PR 标题和描述
- 06推送更改并创建 PR
适用场景
- 01从默认分支上的未提交工作创建 PR
- 02将 Fork 中的更改提交到上游仓库
- 03按仓库模板生成 PR 描述
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ tenfyzhong/ skills-hub --skill create-pr安装后在 Claude Code 中输入/create-pr确认已加载。
详细介绍
创建 PR 技能
从当前工作创建 Pull Request,支持自动创建分支、创建提交、智能检测远程仓库并生成 PR 内容。
前置条件检查(必须先验证)
继续之前,请验证:
# 1. Check if in a git repository
git rev-parse --is-inside-work-tree
# 2. Check if gh CLI is available and authenticated
gh auth status
# 3. Record the current working tree state
git status --porcelain
如果检查失败,请停止并告知用户:
- 不在 git 仓库中 → “此技能需要 git 仓库。请切换到 git 项目目录。”
- gh 未通过身份验证 → “请先运行
gh auth login。”
不要停止,也不要要求用户切换分支、提交更改或暂存更改。在下面的工作流中自动处理当前分支和未提交的更改。
输入
用户可以选择提供:
- 目标基础分支(默认为 main/master)
- 草稿模式标记
- 指定的审阅者
工作流
步骤 1:检测仓库配置
# Get all remotes
git remote -v
# Get current branch name
CURRENT_BRANCH=$(git branch --show-current)
# Detect default branch (main or master)
DEFAULT_BRANCH=$(gh repo view --json defaultBranchRef -q '.defaultBranchRef.name')
# Get repository info
gh repo view --json owner,name,isFork,parent
步骤 2:识别上游和派生仓库远程端
确定远程配置:
# List all remotes with their URLs
git remote -v
# Check if this repo is a fork
IS_FORK=$(gh repo view --json isFork -q '.isFork')
# If it's a fork, get parent info
if [ "$IS_FORK" = "true" ]; then
PARENT_OWNER=$(gh repo view --json parent -q '.parent.owner.login')
PARENT_NAME=$(gh repo view --json parent -q '.parent.name')
fi
远程端分类逻辑:
| 场景 | 上游远程端 | 推送远程端 |
|---|---|---|
| 单个远程端(origin) | origin | origin |
| 派生仓库:origin=fork,upstream=parent | upstream | origin |
| 派生仓库:origin=parent,存在 fork 远程端 | origin | fork 远程端 |
| 多个远程端,其中一个是派生仓库 | 非派生仓库远程端 | 派生仓库远程端 |
检测算法:
# Get current user's GitHub username
CURRENT_USER=$(gh api user -q '.login')
# For each remote, check if it belongs to current user
for remote in $(git remote); do
REMOTE_URL=$(git remote get-url $remote)
# Extract owner from URL (handles both HTTPS and SSH)
REMOTE_OWNER=$(echo "$REMOTE_URL" | sed -E 's/.*[:/]([^/]+)\/[^/]+\.git$/\1/' | sed 's/\.git$//')
if [ "$REMOTE_OWNER" = "$CURRENT_USER" ]; then
FORK_REMOTE=$remote
else
UPSTREAM_REMOTE=$remote
fi
done
# Default fallback
UPSTREAM_REMOTE=${UPSTREAM_REMOTE:-origin}
FORK_REMOTE=${FORK_REMOTE:-origin}
步骤 3:创建功能分支并提交更改
在变基或推送之前,为 PR 准备工作:
- 检查
git status --short、已暂存的更改、未暂存的更改以及未跟踪文件名。 - 如果
CURRENT_BRANCH是DEFAULT_BRANCH、main或master,请根据用户请求和更改生成简洁的分支名称。遵循仓库命名规范(如有),避免与本地和远程分支重名,创建分支并更新CURRENT_BRANCH。 - 如果工作树包含更改,请暂存当前预期的工作并提交。根据请求和差异生成简洁的提交消息,并遵循仓库的提交风格、签署声明和签名要求。
- 创建分支并提交,不要询问用户选择分支名称、切换分支、提供提交消息或自行提交更改。
# Create a feature branch automatically when currently on the base branch.
if [ "$CURRENT_BRANCH" = "$DEFAULT_BRANCH" ] || \
[ "$CURRENT_BRANCH" = "main" ] || \
[ "$CURRENT_BRANCH" = "master" ]; then
# Derive NEW_BRANCH from the request and diff, for example feat/add-export.
# Add a short numeric suffix if the name already exists locally or remotely.
git switch -c "$NEW_BRANCH"
CURRENT_BRANCH=$NEW_BRANCH
fi
# Commit all intended current work when the tree is dirty.
if [ -n "$(git status --porcelain)" ]; then
git status --short
git diff
git diff --cached
git add -A
git diff --cached
# Derive COMMIT_MESSAGE from the request and staged diff. Add flags such as
# -s or -S when required by repository instructions.
git commit -m "$COMMIT_MESSAGE"
fi
不要将编辑器生成的文件、生成的密钥、凭据或无关文件纳入提交。如果仓库说明要求在提交前运行测试,请运行测试并在 PR 描述中注明结果。
步骤 4:同步并变基到上游默认分支
# Fetch latest from upstream
git fetch "$UPSTREAM_REMOTE" "$DEFAULT_BRANCH"
# Rebase current branch onto latest default branch
git rebase "$UPSTREAM_REMOTE/$DEFAULT_BRANCH"
# If rebase fails, inform user
if [ $? -ne 0 ]; then
echo "Rebase failed. Please resolve conflicts manually."
git rebase --abort
exit 1
fi
步骤 5:将分支推送到远程端
检查远程端上是否已存在该分支,然后推送:
# Check if branch exists on the push remote
REMOTE_BRANCH_EXISTS=$(git ls-remote --heads $FORK_REMOTE $CURRENT_BRANCH | wc -l)
if [ "$REMOTE_BRANCH_EXISTS" -eq 0 ]; then
# Branch doesn't exist, push with upstream tracking
git push -u $FORK_REMOTE $CURRENT_BRANCH
else
# Branch exists, force push (after rebase) with lease for safety
git push --force-with-lease $FORK_REMOTE $CURRENT_BRANCH
fi
重要:为确保安全,始终使用 --force-with-lease,不要使用 --force。
步骤 6:收集 PR 内容信息
# Get all commits between default branch and current branch
git log $UPSTREAM_REMOTE/$DEFAULT_BRANCH..HEAD --pretty=format:"%h %s%n%b" --no-merges
# Get the diff summary
git diff --stat $UPSTREAM_REMOTE/$DEFAULT_BRANCH..HEAD
# Get the full diff for analysis
git diff $UPSTREAM_REMOTE/$DEFAULT_BRANCH..HEAD
# Get list of changed files
git diff --name-only $UPSTREAM_REMOTE/$DEFAULT_BRANCH..HEAD
步骤 7:检查 PR 模板
# Check for PR template in common locations
PR_TEMPLATE=""
for template_path in \
".github/pull_request_template.md" \
".github/PULL_REQUEST_TEMPLATE.md" \
"docs/pull_request_template.md" \
"PULL_REQUEST_TEMPLATE.md"; do
if [ -f "$template_path" ]; then
PR_TEMPLATE="$template_path"
break
fi
done
# Also check for template directory
if [ -z "$PR_TEMPLATE" ] && [ -d ".github/PULL_REQUEST_TEMPLATE" ]; then
# Use default template if exists
if [ -f ".github/PULL_REQUEST_TEMPLATE/default.md" ]; then
PR_TEMPLATE=".github/PULL_REQUEST_TEMPLATE/default.md"
fi
fi
# Read template content if found
if [ -n "$PR_TEMPLATE" ]; then
cat "$PR_TEMPLATE"
fi
步骤 8:生成 PR 标题和描述
标题生成规则:
- 如果只有一个提交:使用提交消息的主题行
- 如果有多个提交:概述整体更改
- 如果项目使用约定式提交格式,请遵循该格式:
<type>(<scope>): <description> - 控制在 72 个字符以内
描述生成:
如果存在 PR 模板,请填写模板各部分:
| 常见模板部分 | 填写方式 |
|---|---|
## Summary / ## Description | 概述提交和差异中的更改 |
## Changes / ## What | 列出差异中的关键更改 |
## Why / ## Motivation | 从提交正文中提取原因,或根据更改推断 |
## Testing | 列出已更改的测试文件,或建议手动测试 |
## Screenshots | 检测到 UI 更改时保留占位内容 |
## Checklist | 保留复选框,供用户填写 |
Fixes # / Closes # | 从提交中提取问题引用 |
如果没有模板,则生成结构化描述:
## Summary
[2-3 sentences summarizing what this PR does]
## Changes
- [Key change 1]
- [Key change 2]
- [Key change 3]
## Testing
[How the changes were tested or should be tested]
---
[Any issue references found in commits]
步骤 9:创建 Pull Request
# Determine the base repository for the PR
if [ "$IS_FORK" = "true" ]; then
# For forks, create PR against parent repo
BASE_REPO="$PARENT_OWNER/$PARENT_NAME"
gh pr create \
--repo "$BASE_REPO" \
--base "$DEFAULT_BRANCH" \
--head "$CURRENT_USER:$CURRENT_BRANCH" \
--title "$PR_TITLE" \
--body "$PR_BODY"
else
# For non-forks, create PR in same repo
gh pr create \
--base "$DEFAULT_BRANCH" \
--head "$CURRENT_BRANCH" \
--title "$PR_TITLE" \
--body "$PR_BODY"
fi
使用 HEREDOC 编写正文,以保留格式:
gh pr create --title "$PR_TITLE" --body "$(cat <<'EOF'
## Summary
[Generated summary here]
## Changes
- Change 1
- Change 2
EOF
)"
步骤 10:报告结果
创建 PR 后,提供:
# Get PR URL and details
gh pr view --json url,number,title,state
输出格式
PR 创建成功
PR:#[NUMBER] - [TITLE]
URL:[PR_URL]
Base:[BASE_BRANCH] ← Head:[HEAD_BRANCH]
远程:已推送到 [FORK_REMOTE]
摘要
[简要说明 PR 包含的内容]
已更改的文件
| 文件 | 更改 |
|---|---|
path/to/file.ts | +[additions] -[deletions] |
后续步骤
- 检查 PR 描述,并根据需要进行编辑
- 根据需要添加审阅者
- 等待 CI 检查通过
- 处理审阅意见
错误处理
| 情况 | 操作 |
|---|---|
| 没有领先于 base 的提交 | “没有更改可用于创建 PR。你的分支已与 [base] 保持同步。” |
| 分支名称已存在 | 生成另一个有意义的名称,并添加简短的数字后缀,然后继续。 |
| 提交失败 | 报告确切的失败原因,同时保留用户的工作树和暂存的更改。 |
| Rebase 冲突 | “Rebase 因冲突失败。请手动解决后重新运行。” |
| 推送被拒绝 | “推送失败。请检查你是否有远程仓库的写入权限。” |
| PR 已存在 | “此分支已存在 PR:[URL]。正在打开现有 PR。” |
| 无法访问远程仓库 | “无法访问远程仓库。请使用 gh auth status 检查你的身份验证状态。” |
| Fork 检测失败 | “无法确定 Fork 关系。请指定目标仓库。” |
高级选项
草稿 PR
gh pr create --draft --title "$PR_TITLE" --body "$PR_BODY"
添加审阅者
gh pr create --reviewer "user1,user2" --title "$PR_TITLE" --body "$PR_BODY"
添加标签
gh pr create --label "enhancement,needs-review" --title "$PR_TITLE" --body "$PR_BODY"
关联 Issue
如果提交中引用了 Issue(例如,“Fixes #123”),则自动将其添加到 PR 正文中:
# Extract issue references from commits
ISSUES=$(git log $UPSTREAM_REMOTE/$DEFAULT_BRANCH..HEAD --pretty=format:"%B" | grep -oE "(Fixes|Closes|Resolves) #[0-9]+" | sort -u)
重要说明
- 安全第一:在 Rebase 后推送时,始终使用
--force-with-lease,不要使用--force - 考虑 Fork 情况:自动检测并处理 Fork 工作流
- 遵循模板:始终检查并使用可用的 PR 模板
- 约定式提交:如果项目使用约定式提交,请遵循其格式
- 关联 Issue:保留提交消息中的 Issue 引用
- 提交前审查:创建 PR 前,先显示生成的标题和描述以供用户批准
- 不询问分支或提交操作:自动创建功能分支并提交当前工作;切勿要求用户执行或确认这些操作
评论
支持 Markdown