mcpField
G
git-shortcuts

git-shortcuts

github.com/timschoch开发1729 次安装1 天前更新
代码仓库

关于 git-shortcuts

Git Shortcuts 是一项仅由用户显式调用的技能,将带 `--` 前缀的简写映射为有序的 Git 和 GitHub 操作,涵盖提交、推送和发布。它规定分支、PR、合并及工作树的检查流程,确保操作遵循仓库规则。

主要功能

  1. 01将简写映射为有序操作
  2. 02创建提交、推送和拉取请求
  3. 03规定 PR 合并与发布流程
  4. 04检查分支基准及仓库状态
  5. 05包含分支和工作树保护规则

适用场景

  1. 01提交并推送当前任务的变更
  2. 02从分支创建拉取请求
  3. 03合并 ticket 或 epic 拉取请求
  4. 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(合并)后:

  1. 解析作者的 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。
  2. 获取已合并 PR 的详情:gh pr view --json title,url,body

  3. 撰写一句话摘要(见下文),然后预览:

    Slack #dev:@tim:repo-name -> PostHog 现在通过反向代理运行在 /_s 下,不再受广告拦截器影响。 发布吗?

  4. 如果回答是:通过 mcp__slack__post_message 发布,使用 channel: "#dev",并用 <@USER_ID> 提及用户,让 Slack 将其显示为可点击的 @ 提及。如果回答否:不作处理。

  5. **等待用户回复第 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)。结果为空 → 此仓库没有发布自动化。停止并说明,合并到主干就是此处的全部操作。切勿手动创建标签或部署。

步骤:

  1. 查找发布 PR——gh pr list --base "$trunk" --state open --label "autorelease: pending" --json number,title,url,headRefName

    • 未找到 → 停止并说明:“没有待处理的发布 PR。自上次发布以来没有内容合并到 <trunk>,或者 release-please 仍在运行——请检查 Actions。”
    • 切勿手动创建 PR。 手动创建的 PR 不包含版本升级,也没有变更日志。
  2. 展示即将发布的内容——运行 gh pr diff <number> -- CHANGELOG.md,并打印 PR 标题中的新版本号。询问:“要发布包含这些更改的版本 <version> 吗?”等待答复。

  3. 检查是否可合并——gh pr view <number> --json mergeable,mergeStateStatus

    • MERGEABLE → 继续。
    • CONFLICTING → 停止并说明。切勿手动解决发布 PR 中的冲突——release-please 会重新生成该 PR;请在主干上修复问题根源。
    • UNKNOWN → 每隔 5 秒重新轮询一次,最多 3 次。如果仍为 UNKNOWN,请说明并停止。
  4. 压缩合并——gh pr merge <number> --squash

  5. 监控此次合并触发的运行。 在新的运行排队之前,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 → 输入标签。

  6. Slack 摘要——遵循与 m 之后相同的协议(见上文),并在单行摘要中包含版本号。

  7. 部署注释——如果仓库会在其分析系统中标注部署,请提醒用户按照仓库的分析约定使用 [DEPLOY] <tag>。

--close 命令

释放当前工作树:停止其开发服务器、释放其数据库分支并删除目录。具体操作取决于工作树的所有者——先确认这一点。

  1. 不是工作树? 如果当前目录是主检出目录(git rev-parse --git-common-dir 解析出的路径位于该目录内),则无需关闭任何内容。报告这一点并停止。

  2. 由 Superset 管理的工作树——不做任何操作。 路径位于 ~/.superset/worktrees/ 下。会话关闭时,Superset 会运行 .superset/teardown.sh 并移除工作树,因此 --close 无事可做。报告这一点并停止。

    唯一例外:用户想要立即释放数据库分支,同时保持会话开启 → 运行仓库的 teardown 脚本(bash scripts/teardown.sh — 始终以 0 退出,重复运行也安全),并保留目录。

  3. 其他任何位置——从主检出目录运行一条命令:

    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? → 显示关闭操作将拆除哪些内容

评论

支持 Markdown