关于 git-shortcuts
Git Shortcuts 是一项仅由用户显式调用的技能,将带 `--` 前缀的简写映射为有序的 Git 和 GitHub 操作,涵盖提交、推送和发布。它规定分支、PR、合并及工作树的检查流程,确保操作遵循仓库规则。
主要功能
- 01将简写映射为有序操作
- 02创建提交、推送和拉取请求
- 03规定 PR 合并与发布流程
- 04检查分支基准及仓库状态
- 05包含分支和工作树保护规则
适用场景
- 01提交并推送当前任务的变更
- 02从分支创建拉取请求
- 03合并 ticket 或 epic 拉取请求
- 04发布已开启的 release 拉取请求
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ timschoch/ skilly --skill git-shortcuts安装后在 Claude Code 中输入/git-shortcuts确认已加载。
附带文件LEGACY-STAGING.mdWORKTREE-SETUP.md
详细介绍
Git 快捷操作
安全保障:助手绝不能自主调用此技能。此技能只能由用户调用——仅当用户在消息中明确输入带
--前缀的简写(例如--cp、--cppr)时才运行。助手绝不能自行决定调用此技能。
将每个字母映射到一个操作,并按顺序执行。
分支模型
基于主干开发:ticket → main;如果某个功能涉及多个工单,则为 ticket → epic/<name> → main。合并到主干不会发布任何内容——发布由 --release 完成。
首先,检查仓库是否已完成迁移。 如果仓库仍有 staging 分支,则使用旧的单向模型,以下规则均不适用:
git ls-remote --exit-code --heads origin staging > /dev/null 2>&1 && echo LEGACY
LEGACY → 告知用户,然后读取此文件旁的 LEGACY-STAGING.md 并按其中说明操作。切勿在此类仓库中默默将目标设为主干。
基准分支:绝不硬编码。 如果仓库有自己的辅助工具,优先使用:
branch=$(git symbolic-ref --short HEAD)
trunk=$(node .agents/skills/verify/scripts/default-branch.mjs)
if [ -f .agents/hooks/lib/branch-name.sh ]; then
. .agents/hooks/lib/branch-name.sh
base=$(branch_base "$branch")
else
base=$(git config "branch.${branch}.laicaBase" 2> /dev/null)
case "$base" in
epic/*) git rev-parse --verify --quiet "refs/remotes/origin/$base" > /dev/null || base=$trunk ;;
*) base=$trunk ;;
esac
fi
$trunk 是仓库的默认分支:应读取,而不是自行假定。$base 是 pr 的目标分支:可以是主干,也可以是创建工单分支时所基于的 epic 分支。
错误的基准分支会导致差异范围缩小,而评审报告会将小差异视为干净——因此,如果无法在 origin 上确认 epic/* 基准分支,就回退到主干。绝不能反过来。
简写映射
| 字母 | 操作 |
|---|---|
c | 提交 — 调用 /commit 技能(暂存相关文件、编写符合规范的提交消息、创建提交) |
p | 推送 — git push origin <current-branch> |
pr | 创建 PR — 按照 PR 创建协议 执行 gh pr create(标题 + 正文,--base "$base") |
m | 合并 — 按照合并协议持续检查 PR,直到可以合并。然后提供 Slack 摘要(见下文) |
工单分支适合使用 squash 合并:合并后该分支便会废弃。epic 分支应使用合并提交进行合并——squash 会把逐工单提交压缩在一起,而这些提交正是创建 epic 的原因;此外,release-please 会读取这些提交消息来生成变更日志。
合并协议
完整阅读此技能旁边的 ../babysit-pr/SKILL.md,并按照合并模式执行。其 CI 预算、合并命令和终止状态均保持不变。
- 工单分支:
--merge,即 squash 合并。 - 将
epic/*分支合并到主干:--merge=merge,即合并提交。 - 未安装
babysit-pr:停止,并告知用户运行npx -y github:timschoch/skilly add babysit-pr。绝不要退回到直接运行gh pr merge。 - 循环以 needs-user 或 closed 状态结束:
m步骤失败。停止并将其报告转交给用户。
PR 创建协议
预检。 执行 gh pr view --json url。如果此分支已有已打开的 PR → 报告并停止。然后查看与 origin/$base 的差异,并确认它符合用户提出的目标。
标题。 先写 Conventional Commit 类型,再说明变更为何重要,而不是做了什么。
- 不佳:
perf(server): negotiate per-message deflate on the websocket - 良好:
perf(server): cut websocket frame size by 70% with gzipping
正文。 如果此技能文件旁边存在 ../pr/SKILL.md → 完整阅读,并根据其中的模板撰写正文;以下两条不适用。如果文件不存在 → 以用户自己的话说明问题,然后用几行说明解决方案。绝不要罗列实现内容。
- 不佳:“Removed implicit workspace carryover from every new thread entry point …”
- 良好:“My new worktree default was ignored when starting new threads on existing worktrees.”
无论哪种情况:如果差异超过约 200 行 → 添加简短的“如何审查”指引,指出从哪里开始。正文末尾附上会话提供的署名行。
绝不要创建草稿 PR。 审查机器人只会处理正式 PR。
规则
-
绝不要删除分支。 不要向任何
gh命令传入--delete-branch。不要运行git branch -d或git push origin --delete。如果某个工具或命令会删除分支,请跳过该标志或步骤。合并时,GitHub 会自行删除远程头部分支(delete_branch_on_merge)——这是仓库设置所致,不是你执行的操作,也不是开始传入该标志的理由。 -
按简写中步骤出现的顺序执行(从左到右)。
-
如果某一步失败,停止并报告——不要继续下一步。
-
对于
c:遵循完整的提交协议,但暂存文件的范围仅限于本次对话中完成的工作。根据对话上下文确定相关文件集——即本次会话中读取、编辑或创建的文件。运行git status查看所有已更改内容,然后仅暂存属于此任务的文件。如果有其他与当前任务无关的已更改文件(例如来自并行 Agent 会话的文件),不要暂存。如果无法确定某个文件是否属于本次任务,则排除该文件并说明。绝不要使用git add .或git add -A。暂存之前,按以下确切格式输出范围摘要:In scope: • src/foo/bar.ts • src/foo/baz.ts Excluded: • src/other/thing.ts (reason)
有效组合
所有输入都必须以 -- 开头。
| 输入 | 步骤 |
|---|---|
--c | 提交 |
--p | 推送 |
--cp | 提交 → 推送 |
--pr | 创建 PR |
--prm | 创建 PR → 合并 |
--cppr | 提交 → 推送 → 创建 PR |
--cpprm | 提交 → 推送 → 创建 PR → 合并 |
--ff | 将当前分支从其远程分支快进更新(见下文) |
--release | 发布已打开的发布 PR(见下文)。--pub 是旧名称,功能相同 |
--close | 处置当前工作树——拆除并移除(见下文)。在 Superset 下不执行任何操作 |
其他组合(例如单独使用 --m)不常见——继续操作前请向用户确认。
合并后发送 Slack 摘要
每次成功执行 m(合并)后:
-
解析作者的 Slack 用户 ID:
- 检查环境中是否设置了
SLACK_USER_ID(echo $SLACK_USER_ID)。 - 如果未设置:询问用户“你的 Slack 用户名是什么?(例如
tim)”→ 调用mcp__slack__lookup_user_by_email或mcp__slack__users_lookupByUsername解析出用户 ID → 然后询问“要我将该 ID 以SLACK_USER_ID=<id>的形式保存到.env中吗?”如果回答是,就将这一行追加到.env。
- 检查环境中是否设置了
-
获取已合并 PR 的详情:
gh pr view --json title,url,body -
撰写一句话摘要(见下文),然后预览:
Slack #dev:@tim:repo-name -> PostHog 现在通过反向代理运行在
/_s下,不再受广告拦截器影响。 发布吗? -
如果回答是:通过
mcp__slack__post_message发布,使用channel: "#dev",并用<@USER_ID>提及用户,让 Slack 将其显示为可点击的 @ 提及。如果回答否:不作处理。 -
**等待用户回复第 3/4 步,然后停止。**合并已完成。不要提供
--close或任何后续操作——合并后无需清理。
消息格式: <@USER_ID>: <repo-name> -> <one-liner> <PR-URL>
**撰写一句话摘要:**用德语写一个现在时句子。先说明实际发生了什么变化,而不是提交类型。句子后附上 PR URL(不要嵌入句中)。不要使用项目符号;除非 PR 明显值得庆祝,否则不要使用表情符号。
示例:
- PR 标题:
feat: add reverse proxy for PostHog - 正文:将
/_s路由到 PostHog,避免被广告拦截器屏蔽 - →
<@U0123ABCD>: colin -> PostHog 现在通过反向代理运行在 /_s 下,不再受广告拦截器影响。https://github.com/…
--ff 命令
将当前分支快进到其远程对应分支:git pull --ff-only。
- 未配置上游 →
git fetch origin,然后如果该引用存在,则执行git merge --ff-only origin/<branch>。如果 origin 上不存在该分支 → 报告并停止。 - 无法快进(本地和远程已分叉)→ git 会自行中止;报告分叉情况并停止。绝不改用合并或变基来强行完成。
- 存在未提交的更改也没关系——只有这些更改与更新发生冲突时,git 才会拒绝更新;此时报告并停止。
- 不会触及其他分支,也不会发布任何内容。
--release 命令
发布自上次发布以来合并到主干的所有内容。--pub 是它的旧名称,行为完全相同。
该技能不会计算版本号、创建标签或合并分支。release-please 会在主干上保持一个待处理的发布 PR,并在每次合并后重写它;此命令会检查并合并该 PR。合并后会运行仓库的发布工作流,该工作流会创建标签、迁移生产环境并部署。
没有分支限制——可以从任何分支运行。
预检——查找发布工作流:wf=$(grep -rl release-please .github/workflows/ 2> /dev/null | head -1)。结果为空 → 此仓库没有发布自动化。停止并说明,合并到主干就是此处的全部操作。切勿手动创建标签或部署。
步骤:
-
查找发布 PR——
gh pr list --base "$trunk" --state open --label "autorelease: pending" --json number,title,url,headRefName- 未找到 → 停止并说明:“没有待处理的发布 PR。自上次发布以来没有内容合并到
<trunk>,或者 release-please 仍在运行——请检查 Actions。” - 切勿手动创建 PR。 手动创建的 PR 不包含版本升级,也没有变更日志。
- 未找到 → 停止并说明:“没有待处理的发布 PR。自上次发布以来没有内容合并到
-
展示即将发布的内容——运行
gh pr diff <number> -- CHANGELOG.md,并打印 PR 标题中的新版本号。询问:“要发布包含这些更改的版本<version>吗?”等待答复。 -
检查是否可合并——
gh pr view <number> --json mergeable,mergeStateStatusMERGEABLE→ 继续。CONFLICTING→ 停止并说明。切勿手动解决发布 PR 中的冲突——release-please 会重新生成该 PR;请在主干上修复问题根源。UNKNOWN→ 每隔 5 秒重新轮询一次,最多 3 次。如果仍为UNKNOWN,请说明并停止。
-
压缩合并——
gh pr merge <number> --squash -
监控此次合并触发的运行。 在新的运行排队之前,
gh run list --limit 1仍会返回上一次发布运行,监控它会报告过时的成功结果。将运行固定到此次合并的提交:sha=$(gh pr view <number> --json mergeCommit --jq '.mergeCommit.oid') for _ in $(seq 12); do id=$(gh run list --workflow="$(basename "$wf")" --json databaseId,headSha \ --jq ".[] | select(.headSha==\"$sha\") | .databaseId" | head -1) [ -n "$id" ] && break sleep 10 done [ -n "$id" ] && gh run watch "$id" || echo "Kein Release-Run für $sha nach 2 min — prüf die Actions."报告结果。如果标签创建后部署步骤失败,请告知用户修复方法:Actions → 发布工作流 → Run workflow → 输入标签。
-
Slack 摘要——遵循与
m之后相同的协议(见上文),并在单行摘要中包含版本号。 -
部署注释——如果仓库会在其分析系统中标注部署,请提醒用户按照仓库的分析约定使用
[DEPLOY] <tag>。
--close 命令
释放当前工作树:停止其开发服务器、释放其数据库分支并删除目录。具体操作取决于工作树的所有者——先确认这一点。
-
不是工作树? 如果当前目录是主检出目录(
git rev-parse --git-common-dir解析出的路径位于该目录内),则无需关闭任何内容。报告这一点并停止。 -
由 Superset 管理的工作树——不做任何操作。 路径位于
~/.superset/worktrees/下。会话关闭时,Superset 会运行.superset/teardown.sh并移除工作树,因此--close无事可做。报告这一点并停止。唯一例外:用户想要立即释放数据库分支,同时保持会话开启 → 运行仓库的 teardown 脚本(
bash scripts/teardown.sh— 始终以 0 退出,重复运行也安全),并保留目录。 -
其他任何位置——从主检出目录运行一条命令:
cd "$(git rev-parse --path-format=absolute --git-common-dir)/.." && yarn wt:remove <worktree-path>worktree-remove.sh已将两步串联起来:先在工作树内运行teardown.sh,然后运行git worktree remove。不要事先单独调用teardown.sh。
仓库必须提供这些脚本。 运行前先检查——执行 git grep -q '"wt:remove"' -- package.json;对于没有 package.json 的仓库,则执行 test -f scripts/worktree-remove.sh。如果缺少 → 停止,并将此文件旁边 WORKTREE-SETUP.md 中的设置模板交给用户。 不要自行改用裸命令 git worktree remove:它会跳过 teardown,并泄漏工作树中遗留的内容——仍在运行的开发服务器、尚未删除的数据库分支。
有两点需要注意:
- 从主检出目录运行,而不是从工作树内部运行。 该命令会删除目标目录;如果当前位于该目录中,shell 将失去工作目录,之后的每条命令都会失败。
--close会结束本次会话的工作。 之后无法再运行任何操作——工作树已不存在。先完成其他所有事情,再报告,并将其作为最后一步。
如果工作树有未提交的更改,git worktree remove 会拒绝删除。请先提交或丢弃这些更改;不要使用 --force,否则会丢弃工作成果。
它不会触及任何分支。 无需删除任何内容——合并时 GitHub 会移除远程分支(delete_branch_on_merge),本地分支则会随工作树一起移除。
绝不要主动建议使用 --close。 它不是任何工作流中的步骤——只有用户输入该命令时才运行。合并 PR 并不意味着需要运行它。
如果分支是 epic/*——其数据库分支由多人共享,生命周期也长于工作树,因此 teardown 会保留该分支。请询问:“是否也要删除 Neon 分支 epic/<name>?(yarn neon branches delete epic/<name>)”。该分支没有 TTL,因此不会自行删除。等待用户答复。
? 修饰符
在任何简写的末尾添加 ?,会将最后一步操作替换为检查,而不是执行。链中的所有前置步骤仍会照常运行。
? 只能出现在最末尾——--cp?r 无效。
| 上一个操作 | ? 的行为 |
|---|---|
c | 显示未提交的更改:运行 git status 和 git diff --stat,总结将暂存并提交的内容。不要提交。 |
p | 不执行任何操作——提交消息已说明一切,没有其他有用信息可显示。静默跳过。 |
pr | 检查当前分支是否有已打开的 PR(gh pr view --json state,mergeable,url),并报告其状态和是否已准备好合并。不要创建 PR。 |
m | 报告 PR 的合并状态,而不是执行合并:gh pr view --json state,mergeable,mergeStateStatus,baseRefName,以及将使用的合并方式(--squash;将 epic 合并到 trunk 时使用 --merge)。不要轮询 Vercel——合并不会触发部署。 |
ff | 报告分支落后于/领先于其远程分支的提交数,但不要更新:运行 git fetch origin,然后运行 git rev-list --left-right --count <branch>...origin/<branch>。说明是否可以快进合并。不要拉取。 |
release | 检查已打开的发布 PR:版本、变更日志差异、mergeable 状态。不要合并。--pub? 执行相同命令。 |
close | 报告将要清理的内容:工作树路径、是否由 Superset 拥有、未提交的更改,以及仓库是否提供 wt:remove。不要移除任何内容。 |
| 示例: |
--c?→ 总结未提交的更改--cp?→ 提交,然后跳过(p? 不执行任何操作)--cppr?→ 提交 → 推送 → 检查 PR 状态(不创建)--cpprm?→ 提交 → 推送 → 创建 PR → 报告是否已满足合并条件(不合并)--ff?→ 显示分支落后远程多少(不拉取)--release?→ 显示下一个版本将包含哪些内容--close?→ 显示关闭操作将拆除哪些内容