Branch Orchestration by constellos/claude-code-plugins
npx skills add https://github.com/constellos/claude-code-plugins --skill 'Branch Orchestration'通过自动化命名、问题关联和生命周期操作实现智能 Git 分支管理。
分支编排遵循 {issueNum}-{workType}/{kebab-name} 的命名规范,提供系统化的分支命名和管理。自动将分支关联到 GitHub 问题,检测工作类型,并管理分支生命周期,包括创建、重命名、远程同步和清理。
格式:{issueNumber}-{workType}/{kebab-case-title}
示例:
42-feature/add-dark-mode123-fix/safari-auth-bug7-docs/update-readme99-refactor/simplify-api广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
使用智能命名创建分支:
# 使用命名工具手动创建
ISSUE_NUM=42
WORK_TYPE="feature"
TITLE="Add dark mode support"
# 生成分支名称
BRANCH_NAME=$(generateBranchName $ISSUE_NUM "$WORK_TYPE" "$TITLE")
# 结果:"42-feature/add-dark-mode-support"
# 创建并切换到分支
git checkout -b "$BRANCH_NAME"
# 推送到远程并设置跟踪
git push -u origin "$BRANCH_NAME"
工具函数:
generateBranchName(issueNumber, workType, title) - 生成格式化名称toKebabCase(title) - 将标题转换为 kebab-case(最多 40 个字符)validateBranchName(branchName) - 检查命名规范重命名分支并同步到远程:
# 获取当前分支
OLD_BRANCH=$(git rev-parse --abbrev-ref HEAD)
# 生成新名称
NEW_BRANCH="42-feature/add-dark-mode"
# 重命名本地分支
git branch -m "$OLD_BRANCH" "$NEW_BRANCH"
# 检查旧分支是否存在于远程
if git ls-remote --heads origin "$OLD_BRANCH" | grep -q "$OLD_BRANCH"; then
# 推送新分支并删除旧远程分支
git push -u origin "$NEW_BRANCH"
git push origin --delete "$OLD_BRANCH"
else
# 仅为新分支设置上游
git push -u origin "$NEW_BRANCH"
fi
工具函数:
parseBranchName(branchName) - 提取组件(问题编号、工作类型、标题)extractIssueNumber(branchName) - 从分支名称中获取问题编号将分支关联到 GitHub 问题:
# 将分支引用添加到问题正文
ISSUE_NUM=42
BRANCH_NAME="42-feature/add-dark-mode"
CURRENT_BODY=$(gh issue view $ISSUE_NUM --json body -q .body)
UPDATED_BODY="$CURRENT_BODY
---
**分支:** \`$BRANCH_NAME\`"
echo "$UPDATED_BODY" | gh issue edit $ISSUE_NUM --body-file -
# 保存到状态文件
STATE_FILE=".claude/logs/branch-issues.json"
jq --arg branch "$BRANCH_NAME" --arg issue "$ISSUE_NUM" \
'.[$branch] = {issueNumber: ($issue | tonumber)}' \
"$STATE_FILE" > tmp.json && mv tmp.json "$STATE_FILE"
状态文件:
.claude/logs/branch-issues.json - 将分支名称映射到问题编号清理已合并或过期的分支:
# 删除已合并的本地分支
git branch --merged main | grep -v "^\*\|main\|master" | xargs -n 1 git branch -d
# 删除已合并的远程分支
gh pr list --state merged --json headRefName -q '.[].headRefName' | \
xargs -I {} git push origin --delete {}
# 删除过期分支(30 天内无提交)
git for-each-ref --sort=-committerdate refs/heads/ \
--format='%(refname:short) %(committerdate:relative)' | \
awk '$2 ~ /months/ && $3 >= 1 {print $1}' | \
xargs -n 1 git branch -D
根据上下文自动检测工作类型:
import { detectWorkType } from '../shared/hooks/utils/work-type-detector.js';
// 从提示中检测
const workType = detectWorkType('fix the authentication bug');
// 返回:'fix'
// 从问题标签中检测
const workType = detectWorkType(
'Update authentication system',
['bug', 'priority:high']
);
// 返回:'fix'(从 'bug' 标签检测到)
工作类型:
feature - 新功能fix - 错误修复chore - 维护任务docs - 文档refactor - 代码改进此技能补充了自动钩子:
| 钩子 | 自动行为 | 何时使用此技能 |
|---|---|---|
| create-issue-on-prompt | 在问题创建后重命名分支 | 在问题创建前重命名,自定义命名 |
| add-github-context | 从分支名称中发现问题 | 手动分支-问题关联 |
状态文件:
.claude/logs/branch-issues.json - 分支 → 问题映射generateBranchName(issueNumber: number, workType: WorkType, title: string): string
生成格式化的分支名称。
示例:
generateBranchName(42, 'feature', 'Add Dark Mode')
// 返回:"42-feature/add-dark-mode"
parseBranchName(branchName: string): ParsedBranchName
将分支名称解析为组件。
示例:
parseBranchName('42-feature/add-dark-mode')
// 返回:{ issueNumber: 42, workType: 'feature', title: 'add-dark-mode' }
parseBranchName('123-fix-auth-bug')
// 返回:{ issueNumber: 123, title: 'fix-auth-bug' }
validateBranchName(branchName: string): BranchValidation
根据规范验证分支名称。
示例:
validateBranchName('42-feature/add-dark-mode')
// 返回:{ valid: true }
validateBranchName('invalid name with spaces')
// 返回:{ valid: false, reason: 'Branch name cannot contain spaces' }
extractIssueNumber(branchName: string): number | null
从分支名称中提取问题编号。
示例:
extractIssueNumber('42-feature/add-dark-mode')
// 返回:42
extractIssueNumber('main')
// 返回:null
# 获取问题详情
ISSUE_NUM=42
ISSUE_DATA=$(gh issue view $ISSUE_NUM --json title,labels)
TITLE=$(echo "$ISSUE_DATA" | jq -r '.title')
LABELS=$(echo "$ISSUE_DATA" | jq -r '.labels[].name' | tr '\n' ',')
# 检测工作类型
WORK_TYPE=$(detectWorkType "$TITLE" "$LABELS")
# 返回:'feature' 或 'fix' 或 'chore' 等
# 生成分支名称
BRANCH_NAME=$(generateBranchName $ISSUE_NUM "$WORK_TYPE" "$TITLE")
# 返回:"42-feature/add-dark-mode-support"
# 创建并切换
git checkout -b "$BRANCH_NAME"
git push -u origin "$BRANCH_NAME"
# 关联到问题
echo "Branch \`$BRANCH_NAME\` created" | gh issue comment $ISSUE_NUM --body-file -
# 当前分支不遵循规范
CURRENT=$(git rev-parse --abbrev-ref HEAD)
# 例如:"claude-agile-narwhal-x7h3k"
# 获取关联的问题(如果存在)
ISSUE_NUM=$(parseIssueFromBranch "$CURRENT")
if [ -z "$ISSUE_NUM" ]; then
echo "No issue linked to this branch"
exit 1
fi
# 获取问题详情
ISSUE_DATA=$(gh issue view $ISSUE_NUM --json title,labels)
TITLE=$(echo "$ISSUE_DATA" | jq -r '.title')
LABELS=$(echo "$ISSUE_DATA" | jq -r '.labels[].name' | tr '\n' ',')
# 生成新名称
WORK_TYPE=$(detectWorkType "$TITLE" "$LABELS")
NEW_BRANCH=$(generateBranchName $ISSUE_NUM "$WORK_TYPE" "$TITLE")
# 重命名并同步到远程
git branch -m "$CURRENT" "$NEW_BRANCH"
git push -u origin "$NEW_BRANCH"
git push origin --delete "$CURRENT" 2>/dev/null || true
# 获取当前分支
BRANCH=$(git rev-parse --abbrev-ref HEAD)
# 跳过受保护分支的验证
if [[ "$BRANCH" =~ ^(main|master|develop)$ ]]; then
exit 0
fi
# 验证格式
if ! validateBranchName "$BRANCH"; then
echo "❌ 分支名称 '$BRANCH' 不遵循规范:{issueNum}-{workType}/{kebab-name}"
echo "示例:42-feature/add-dark-mode, 123-fix/safari-bug"
exit 1
fi
# 检查问题是否存在
ISSUE_NUM=$(extractIssueNumber "$BRANCH")
if [ -n "$ISSUE_NUM" ]; then
if ! gh issue view $ISSUE_NUM &>/dev/null; then
echo "⚠️ 分支名称中引用的问题 #$ISSUE_NUM 不存在"
fi
fi
# 获取所有已合并的分支
MERGED=$(git branch --merged main | grep -v "^\*\|main\|master")
for branch in $MERGED; do
# 解析分支名称
PARSED=$(parseBranchName "$branch")
ISSUE_NUM=$(echo "$PARSED" | jq -r '.issueNumber // empty')
# 检查问题是否已关闭
if [ -n "$ISSUE_NUM" ]; then
STATE=$(gh issue view $ISSUE_NUM --json state -q .state 2>/dev/null || echo "")
if [ "$STATE" = "CLOSED" ]; then
echo "删除已合并分支:$branch(问题 #$ISSUE_NUM 已关闭)"
git branch -d "$branch"
git push origin --delete "$branch" 2>/dev/null || true
fi
else
echo "删除已合并分支:$branch(无关联问题)"
git branch -d "$branch"
fi
done
{issueNum}-{workType}/{kebab-name}validateBranchName() 检查格式.claude/logs/branch-issues.json 同步detectWorkType() 自动分类-u 标志# 从当前上下文自动检测问题
ISSUE_NUM=$(cat .claude/logs/branch-issues.json | jq -r '.[] | .issueNumber' | head -1)
if [ -n "$ISSUE_NUM" ]; then
ISSUE_DATA=$(gh issue view $ISSUE_NUM --json title,labels)
TITLE=$(echo "$ISSUE_DATA" | jq -r '.title')
WORK_TYPE=$(detectWorkType "$TITLE")
BRANCH_NAME=$(generateBranchName $ISSUE_NUM "$WORK_TYPE" "$TITLE")
git checkout -b "$BRANCH_NAME"
git push -u origin "$BRANCH_NAME"
fi
# 切换到问题 #42 的分支
ISSUE_NUM=42
BRANCH=$(git branch -a | grep -E "^[ *]*$ISSUE_NUM-" | sed 's/^[ *]*//' | head -1)
if [ -n "$BRANCH" ]; then
git checkout "$BRANCH"
else
echo "未找到问题 #$ISSUE_NUM 的分支"
fi
# 列出所有功能分支
git branch | grep -E "feature/" | sed 's/^[ *]*//'
# 列出所有修复分支
git branch | grep -E "fix/" | sed 's/^[ *]*//'
每周安装数
0
仓库
GitHub 星标数
5
首次出现
1970年1月1日
安全审计
Intelligent Git branch management with automated naming, issue linking, and lifecycle operations.
Branch Orchestration provides systematic branch naming and management following the convention {issueNum}-{workType}/{kebab-name}. Automatically links branches to GitHub issues, detects work types, and manages branch lifecycle including creation, renaming, remote sync, and cleanup.
Format: {issueNumber}-{workType}/{kebab-case-title}
Examples:
42-feature/add-dark-mode123-fix/safari-auth-bug7-docs/update-readme99-refactor/simplify-apiCreate branches with intelligent naming:
# Manual creation with naming utilities
ISSUE_NUM=42
WORK_TYPE="feature"
TITLE="Add dark mode support"
# Generate branch name
BRANCH_NAME=$(generateBranchName $ISSUE_NUM "$WORK_TYPE" "$TITLE")
# Result: "42-feature/add-dark-mode-support"
# Create and checkout branch
git checkout -b "$BRANCH_NAME"
# Push to remote with tracking
git push -u origin "$BRANCH_NAME"
Utilities:
generateBranchName(issueNumber, workType, title) - Generate formatted nametoKebabCase(title) - Convert title to kebab-case (max 40 chars)validateBranchName(branchName) - Check naming conventionsRename branches with remote sync:
# Get current branch
OLD_BRANCH=$(git rev-parse --abbrev-ref HEAD)
# Generate new name
NEW_BRANCH="42-feature/add-dark-mode"
# Rename local branch
git branch -m "$OLD_BRANCH" "$NEW_BRANCH"
# Check if old branch exists on remote
if git ls-remote --heads origin "$OLD_BRANCH" | grep -q "$OLD_BRANCH"; then
# Push new branch and delete old remote
git push -u origin "$NEW_BRANCH"
git push origin --delete "$OLD_BRANCH"
else
# Just set upstream for new branch
git push -u origin "$NEW_BRANCH"
fi
Utilities:
parseBranchName(branchName) - Extract components (issue#, work type, title)extractIssueNumber(branchName) - Get issue number from branch nameLink branches to GitHub issues:
# Add branch reference to issue body
ISSUE_NUM=42
BRANCH_NAME="42-feature/add-dark-mode"
CURRENT_BODY=$(gh issue view $ISSUE_NUM --json body -q .body)
UPDATED_BODY="$CURRENT_BODY
---
**Branch:** \`$BRANCH_NAME\`"
echo "$UPDATED_BODY" | gh issue edit $ISSUE_NUM --body-file -
# Save to state file
STATE_FILE=".claude/logs/branch-issues.json"
jq --arg branch "$BRANCH_NAME" --arg issue "$ISSUE_NUM" \
'.[$branch] = {issueNumber: ($issue | tonumber)}' \
"$STATE_FILE" > tmp.json && mv tmp.json "$STATE_FILE"
State File:
.claude/logs/branch-issues.json - Maps branch names to issue numbersClean up merged or stale branches:
# Delete merged local branches
git branch --merged main | grep -v "^\*\|main\|master" | xargs -n 1 git branch -d
# Delete merged remote branches
gh pr list --state merged --json headRefName -q '.[].headRefName' | \
xargs -I {} git push origin --delete {}
# Delete stale branches (no commits in 30 days)
git for-each-ref --sort=-committerdate refs/heads/ \
--format='%(refname:short) %(committerdate:relative)' | \
awk '$2 ~ /months/ && $3 >= 1 {print $1}' | \
xargs -n 1 git branch -D
Automatically detect work type from context:
import { detectWorkType } from '../shared/hooks/utils/work-type-detector.js';
// From prompt
const workType = detectWorkType('fix the authentication bug');
// Returns: 'fix'
// From issue labels
const workType = detectWorkType(
'Update authentication system',
['bug', 'priority:high']
);
// Returns: 'fix' (detected from 'bug' label)
Work Types:
feature - New functionalityfix - Bug fixeschore - Maintenance tasksdocs - Documentationrefactor - Code improvementsThis skill complements the automatic hooks:
| Hook | Automatic Behavior | When to Use Skill |
|---|---|---|
| create-issue-on-prompt | Renames branch after issue creation | Rename before issue creation, custom naming |
| add-github-context | Discovers issue from branch name | Manual branch-issue linking |
State Files:
.claude/logs/branch-issues.json - Branch → Issue mappinggenerateBranchName(issueNumber: number, workType: WorkType, title: string): string
Generates formatted branch name.
Example:
generateBranchName(42, 'feature', 'Add Dark Mode')
// Returns: "42-feature/add-dark-mode"
parseBranchName(branchName: string): ParsedBranchName
Parses branch name into components.
Example:
parseBranchName('42-feature/add-dark-mode')
// Returns: { issueNumber: 42, workType: 'feature', title: 'add-dark-mode' }
parseBranchName('123-fix-auth-bug')
// Returns: { issueNumber: 123, title: 'fix-auth-bug' }
validateBranchName(branchName: string): BranchValidation
Validates branch name against conventions.
Example:
validateBranchName('42-feature/add-dark-mode')
// Returns: { valid: true }
validateBranchName('invalid name with spaces')
// Returns: { valid: false, reason: 'Branch name cannot contain spaces' }
extractIssueNumber(branchName: string): number | null
Extracts issue number from branch name.
Example:
extractIssueNumber('42-feature/add-dark-mode')
// Returns: 42
extractIssueNumber('main')
// Returns: null
# Get issue details
ISSUE_NUM=42
ISSUE_DATA=$(gh issue view $ISSUE_NUM --json title,labels)
TITLE=$(echo "$ISSUE_DATA" | jq -r '.title')
LABELS=$(echo "$ISSUE_DATA" | jq -r '.labels[].name' | tr '\n' ',')
# Detect work type
WORK_TYPE=$(detectWorkType "$TITLE" "$LABELS")
# Returns: 'feature' or 'fix' or 'chore', etc.
# Generate branch name
BRANCH_NAME=$(generateBranchName $ISSUE_NUM "$WORK_TYPE" "$TITLE")
# Returns: "42-feature/add-dark-mode-support"
# Create and checkout
git checkout -b "$BRANCH_NAME"
git push -u origin "$BRANCH_NAME"
# Link to issue
echo "Branch \`$BRANCH_NAME\` created" | gh issue comment $ISSUE_NUM --body-file -
# Current branch doesn't follow convention
CURRENT=$(git rev-parse --abbrev-ref HEAD)
# e.g., "claude-agile-narwhal-x7h3k"
# Get linked issue (if exists)
ISSUE_NUM=$(parseIssueFromBranch "$CURRENT")
if [ -z "$ISSUE_NUM" ]; then
echo "No issue linked to this branch"
exit 1
fi
# Get issue details
ISSUE_DATA=$(gh issue view $ISSUE_NUM --json title,labels)
TITLE=$(echo "$ISSUE_DATA" | jq -r '.title')
LABELS=$(echo "$ISSUE_DATA" | jq -r '.labels[].name' | tr '\n' ',')
# Generate new name
WORK_TYPE=$(detectWorkType "$TITLE" "$LABELS")
NEW_BRANCH=$(generateBranchName $ISSUE_NUM "$WORK_TYPE" "$TITLE")
# Rename with remote sync
git branch -m "$CURRENT" "$NEW_BRANCH"
git push -u origin "$NEW_BRANCH"
git push origin --delete "$CURRENT" 2>/dev/null || true
# Get current branch
BRANCH=$(git rev-parse --abbrev-ref HEAD)
# Skip validation for protected branches
if [[ "$BRANCH" =~ ^(main|master|develop)$ ]]; then
exit 0
fi
# Validate format
if ! validateBranchName "$BRANCH"; then
echo "❌ Branch name '$BRANCH' doesn't follow convention: {issueNum}-{workType}/{kebab-name}"
echo "Examples: 42-feature/add-dark-mode, 123-fix/safari-bug"
exit 1
fi
# Check if issue exists
ISSUE_NUM=$(extractIssueNumber "$BRANCH")
if [ -n "$ISSUE_NUM" ]; then
if ! gh issue view $ISSUE_NUM &>/dev/null; then
echo "⚠️ Issue #$ISSUE_NUM referenced in branch name doesn't exist"
fi
fi
# Get all merged branches
MERGED=$(git branch --merged main | grep -v "^\*\|main\|master")
for branch in $MERGED; do
# Parse branch name
PARSED=$(parseBranchName "$branch")
ISSUE_NUM=$(echo "$PARSED" | jq -r '.issueNumber // empty')
# Check if issue is closed
if [ -n "$ISSUE_NUM" ]; then
STATE=$(gh issue view $ISSUE_NUM --json state -q .state 2>/dev/null || echo "")
if [ "$STATE" = "CLOSED" ]; then
echo "Deleting merged branch: $branch (issue #$ISSUE_NUM closed)"
git branch -d "$branch"
git push origin --delete "$branch" 2>/dev/null || true
fi
else
echo "Deleting merged branch: $branch (no linked issue)"
git branch -d "$branch"
fi
done
{issueNum}-{workType}/{kebab-name}validateBranchName() to check format.claude/logs/branch-issues.json synceddetectWorkType()-u flag when pushing new branches# Auto-detect issue from current context
ISSUE_NUM=$(cat .claude/logs/branch-issues.json | jq -r '.[] | .issueNumber' | head -1)
if [ -n "$ISSUE_NUM" ]; then
ISSUE_DATA=$(gh issue view $ISSUE_NUM --json title,labels)
TITLE=$(echo "$ISSUE_DATA" | jq -r '.title')
WORK_TYPE=$(detectWorkType "$TITLE")
BRANCH_NAME=$(generateBranchName $ISSUE_NUM "$WORK_TYPE" "$TITLE")
git checkout -b "$BRANCH_NAME"
git push -u origin "$BRANCH_NAME"
fi
# Switch to branch for issue #42
ISSUE_NUM=42
BRANCH=$(git branch -a | grep -E "^[ *]*$ISSUE_NUM-" | sed 's/^[ *]*//' | head -1)
if [ -n "$BRANCH" ]; then
git checkout "$BRANCH"
else
echo "No branch found for issue #$ISSUE_NUM"
fi
# List all feature branches
git branch | grep -E "feature/" | sed 's/^[ *]*//'
# List all fix branches
git branch | grep -E "fix/" | sed 's/^[ *]*//'
Weekly Installs
0
Repository
GitHub Stars
5
First Seen
Jan 1, 1970
Security Audits
agent-browser 浏览器自动化工具 - Vercel Labs 命令行网页操作与测试
144,300 周安装