git-shortcuts
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGit Shortcuts
Git快捷命令
SAFEGUARD: This skill must NEVER be invoked autonomously by the assistant. It is exclusively user-invoked — only run when the user explicitly types aprefixed shorthand (e.g.--,--cp) in their message. The assistant must never decide on its own to call this skill.--cppr
Map each letter to an action and execute them in sequence.
安全防护:此技能绝不能由助手自主调用。它仅能由用户触发——仅当用户在消息中明确输入以为前缀的简写(例如--、--cp)时才可运行。助手不得自行决定调用此技能。--cppr
将每个字母映射为对应的操作,并按顺序执行。
Branch model
分支模型
Trunk-based: , or when a feature spans several tickets. Merging into the trunk ships nothing — does that.
ticket → mainticket → epic/<name> → main--releaseFirst, check the repo has migrated. A repo that still has a branch runs the old one-directional model and none of the rules below apply to it:
stagingbash
git ls-remote --exit-code --heads origin staging > /dev/null 2>&1 && echo LEGACYLEGACYLEGACY-STAGING.mdBase branch: never hardcode it. Prefer the repo's own helper when it has one:
bash
branch=$(git symbolic-ref --short HEAD)
trunk=$(git symbolic-ref --short refs/remotes/origin/HEAD 2> /dev/null | sed 's|^origin/||')
trunk=${trunk:-main}
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$trunkmain$baseprA wrong base produces a smaller diff, and a small diff is what a review reports as clean — so an base that cannot be verified on falls back to the trunk. Never the other way round.
epic/*origin基于主干的模型:,当功能涉及多个工单时则为。合并到主干不会触发任何发布操作——只有命令才会执行发布。
ticket → mainticket → epic/<name> → main--release首先,检查仓库是否已迁移。 仍包含分支的仓库使用旧的单向模型,以下规则均不适用于此类仓库:
stagingbash
git ls-remote --exit-code --heads origin staging > /dev/null 2>&1 && echo LEGACY如果输出 → 告知用户,然后阅读此文件旁的并遵循其中的规则。绝不能在这类仓库中静默地以主干为目标。
LEGACYLEGACY-STAGING.md基准分支:绝不要硬编码。 如果仓库有自带的辅助工具,优先使用:
bash
branch=$(git symbolic-ref --short HEAD)
trunk=$(git symbolic-ref --short refs/remotes/origin/HEAD 2> /dev/null | sed 's|^origin/||')
trunk=${trunk:-main}
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$trunkmain$basepr错误的基准分支会产生更小的差异,而小差异会被评审视为干净——因此如果基准分支在上无法验证,则回退到主干。绝不能反向操作。
epic/*originShorthand map
简写映射
| Letter | Action |
|---|---|
| Commit — invoke the |
| Push — |
| Create PR — |
| Merge — |
Squash is right for a ticket branch: it dies after merge. An epic merges with a merge commit — squashing would collapse the per-ticket commits that were the reason to open an epic, and release-please reads those commit messages to build the changelog.
| 字母 | 操作 |
|---|---|
| 提交——调用 |
| 推送——执行 |
| 创建PR——遵循PR创建流程执行 |
| 合并——执行 |
对于工单分支,压缩合并是合适的:分支在合并后会被废弃。epic分支使用合并提交进行合并——压缩会抹去创建epic的核心原因(即每个工单的独立提交),而release-please需要读取这些提交信息来构建变更日志。
Rules
规则
-
Never delete branches. Do not passto any
--delete-branchcommand. Do not runghorgit branch -d. If a tool or command would delete a branch, skip that flag or step entirely. GitHub deletes the remote head branch itself on merge (git push origin --delete) — that is the repo setting doing it, not you, and it is not a reason to start passing the flag.delete_branch_on_merge -
Execute steps in the order they appear in the shorthand (left to right).
-
If a step fails, stop and report — don't continue to the next step.
-
For: follow the full commit protocol, but scope the staged files to only the work done in this conversation. Derive the relevant file set from the conversation context — which files were read, edited, or created during this session. Run
cto see everything dirty, then stage only the files that belong to this task. If there are other dirty files unrelated to the current task (e.g. from parallel agent sessions), leave them unstaged. If you're unsure whether a file is in scope, exclude it and mention it. Never usegit statusorgit add .. Before staging, output a scoping summary in this exact format:git add -AIn scope: • src/foo/bar.ts • src/foo/baz.ts Excluded: • src/other/thing.ts (reason)
-
绝不要删除分支。 不要在任何命令中传递
gh参数。不要执行--delete-branch或git branch -d。如果工具或命令会删除分支,请完全跳过该参数或步骤。GitHub会在合并时自动删除远程头部分支(git push origin --delete)——这是仓库设置的行为,并非由你执行,也不是你开始传递该参数的理由。delete_branch_on_merge -
按照简写中出现的顺序(从左到右)执行步骤。
-
如果某一步失败,停止操作并报告——不要继续执行下一步。
-
对于命令:遵循完整的提交流程,但仅暂存本次对话中处理的文件。从对话上下文推导相关文件集——本次会话中读取、编辑或创建的文件。执行
c查看所有未提交文件,然后仅暂存属于当前任务的文件。如果存在与当前任务无关的其他未提交文件(例如来自并行Agent会话),请保持其未暂存状态。如果不确定某文件是否属于当前范围,请排除它并说明原因。绝不要使用git status或git add .。暂存前,必须按照以下格式输出范围汇总:git add -A纳入范围: • src/foo/bar.ts • src/foo/baz.ts 排除范围: • src/other/thing.ts (原因)
Valid combinations
有效组合
All inputs must be prefixed with .
--| Input | Steps |
|---|---|
| commit |
| push |
| commit → push |
| create PR |
| create PR → merge |
| commit → push → create PR |
| commit → push → create PR → merge |
| fast-forward the current branch from its remote (see below) |
| ship the open release PR (see below). |
| dispose of the current worktree — teardown + remove (see below). No-op under Superset |
Other combinations (e.g. alone) are unusual — ask the user to confirm before proceeding.
--m所有输入必须以为前缀。
--| 输入 | 步骤 |
|---|---|
| 提交 |
| 推送 |
| 提交 → 推送 |
| 创建PR |
| 创建PR → 合并 |
| 提交 → 推送 → 创建PR |
| 提交 → 推送 → 创建PR → 合并 |
| 将当前分支快进至远程分支(见下文) |
| 发布已打开的版本PR(见下文)。 |
| 清理当前工作区——拆除并移除(见下文)。在Superset环境下无操作 |
其他组合(例如单独使用)不常见——执行前请先询问用户确认。
--mSlack summary after merge
合并后的Slack汇总
After every successful (merge):
m-
Resolve the author's Slack user ID:
- Check if is set in the environment (
SLACK_USER_ID).echo $SLACK_USER_ID - If not set: ask the user "Was ist dein Slack-Handle? (z.B. )" → call
timormcp__slack__lookup_user_by_emailto resolve to a user ID → then ask "Soll ich die ID alsmcp__slack__users_lookupByUsernameinSLACK_USER_ID=<id>speichern?" If yes, append the line to.env..env
- Check if
-
Fetch the merged PR details:
gh pr view --json title,url,body -
Compose a one-liner (see below), then show it as a preview:Slack #dev: @tim: repo-name -> PostHog läuft jetzt via Reverse Proxy unter— kein Adblocker-Problem mehr. <PR-URL> Posten?
/_s -
If yes: post viawith
mcp__slack__post_message, usingchannel: "#dev"for the mention so Slack renders it as a clickable @-mention. If no: skip silently.<@USER_ID> -
Wait for the user's response to step 3/4, then stop. The merge is finished. Do not offeror any other follow-up — nothing needs cleaning up after a merge.
--close
Message format:
<@USER_ID>: <repo-name> -> <one-liner> <PR-URL>Composing the one-liner: One sentence, present tense, German. Lead with what changed in practice, not the commit type. Append the PR URL after the sentence (not embedded). No bullet points, no emoji unless the PR clearly calls for celebration.
Example:
- PR title:
feat: add reverse proxy for PostHog - Body: routes to PostHog, avoids adblockers
/_s - →
<@U0123ABCD>: colin -> PostHog läuft jetzt via Reverse Proxy unter /_s — kein Adblocker-Problem mehr. https://github.com/…
每次成功执行(合并)后:
m-
解析作者的Slack用户ID:
- 检查环境变量中是否设置了(执行
SLACK_USER_ID)。echo $SLACK_USER_ID - 如果未设置:询问用户“Was ist dein Slack-Handle? (z.B. )”(你的Slack用户名是什么?例如
tim)→ 调用tim或mcp__slack__lookup_user_by_email解析为用户ID → 然后询问“Soll ich die ID alsmcp__slack__users_lookupByUsernameinSLACK_USER_ID=<id>speichern?”(是否要将ID保存到.env文件中,格式为.env?)。如果用户同意,将该行追加到SLACK_USER_ID=<id>文件中。.env
- 检查环境变量中是否设置了
-
获取合并后的PR详情:执行
gh pr view --json title,url,body -
编写单行消息(见下文),然后展示预览:Slack #dev: @tim: repo-name -> PostHog läuft jetzt via Reverse Proxy unter— kein Adblocker-Problem mehr. <PR-URL> 发布?
/_s -
如果用户同意:通过发布到
mcp__slack__post_message,使用channel: "#dev"进行提及,使Slack将其渲染为可点击的@提及。如果用户不同意:静默跳过。<@USER_ID> -
等待用户对步骤3/4的回复,然后停止操作。 合并已完成。不要主动提供或其他后续操作——合并后无需清理任何内容。
--close
消息格式:
<@USER_ID>: <repo-name> -> <单行描述> <PR-URL>编写单行描述: 一句话,一般现在时,德语。重点描述实际变更内容,而非提交类型。在句子后追加PR URL(不要嵌入)。不要使用项目符号,除非PR明显需要庆祝,否则不要使用表情符号。
示例:
- PR标题:
feat: add reverse proxy for PostHog - PR正文:将路由到PostHog,避免广告拦截
/_s - →
<@U0123ABCD>: colin -> PostHog läuft jetzt via Reverse Proxy unter /_s — kein Adblocker-Problem mehr. https://github.com/…
The --ff
command
--ff--ff
命令
--ffFast-forwards the current branch to its remote counterpart: .
git pull --ff-only- No upstream configured → , then
git fetch originif that ref exists. Missing on origin → report and stop.git merge --ff-only origin/<branch> - Fast-forward not possible (local and remote diverged) → git aborts on its own; report the divergence and stop. Never fall back to a merge or rebase to force it through.
- Uncommitted changes are fine — git refuses the update only if they collide; then report and stop.
- Touches no other branches, ships nothing.
将当前分支快进至对应的远程分支:执行。
git pull --ff-only- 未配置上游分支 → 执行,如果
git fetch origin引用存在,则执行origin/<branch>。如果远程不存在该分支 → 报告并停止。git merge --ff-only origin/<branch> - 无法快进(本地与远程分支已分叉)→ Git会自动终止操作;报告分叉情况并停止。绝不要回退到合并或变基来强制完成。
- 存在未提交变更没问题——只有当变更冲突时Git才会拒绝更新;此时报告并停止。
- 不涉及其他分支,不执行任何发布操作。
The --release
command
--release--release
命令
--releaseShips whatever has been merged into the trunk since the last release. is the old name for it and behaves identically.
--pubThe skill does not compute a version, create a tag, or merge branches. release-please keeps one release PR open against the trunk and rewrites it on every merge; this command reviews that PR and merges it. Merging it runs the repo's release workflow, which tags, migrates production and deploys.
No branch guard — can be run from any branch.
Preflight — find the release workflow: . Empty → this repo has no release automation. Stop and report that merging to the trunk is all there is here. Never tag or deploy by hand.
wf=$(grep -rl release-please .github/workflows/ 2> /dev/null | head -1)Steps:
-
Find the release PR —
gh pr list --base "$trunk" --state open --label "autorelease: pending" --json number,title,url,headRefName- Not found → stop and report: "Kein offener Release-PR. Es wurde seit dem letzten Release nichts nach gemerged, oder release-please läuft noch — prüf die Actions."
<trunk> - Never create it by hand. A hand-made PR carries no version bump and no changelog.
- Not found → stop and report: "Kein offener Release-PR. Es wurde seit dem letzten Release nichts nach
-
Show what would ship —and print the new version from the PR title. Ask: "Release
gh pr diff <number> -- CHANGELOG.mdmit diesen Änderungen veröffentlichen?" Wait for the answer.<version> -
Check mergeability —
gh pr view <number> --json mergeable,mergeStateStatus- → proceed.
MERGEABLE - → stop and report. Do not resolve conflicts in a release PR by hand — release-please regenerates it; fix the cause on the trunk instead.
CONFLICTING - → re-poll up to 3 times (5 s apart). If still
UNKNOWN, report and stop.UNKNOWN
-
Squash merge —
gh pr merge <number> --squash -
Watch the run this merge created.still returns the previous release run until the new one is queued, and watching that one reports a stale success. Pin the run to the merge commit:
gh run list --limit 1bashsha=$(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."Report the outcome. If the deploy step failed after the tag was created, tell the user the repair path: Actions → the release workflow → Run workflow → enter the tag. -
Slack summary — same protocol as after(see above), with the version in the one-liner.
m -
Deploy annotation — if the repo annotates deploys in its analytics, remind the user:per the repo's analytics conventions.
[DEPLOY] <tag>
发布自上次版本以来合并到主干的所有内容。是该命令的旧名称,行为完全相同。
--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- 未找到 → 停止操作并报告:"Kein offener Release-PR. Es wurde seit dem letzten Release nichts nach gemerged, oder release-please läuft noch — prüf die Actions."(无打开的版本PR。自上次版本以来没有内容合并到
<trunk>,或者release-please仍在运行——请检查Actions。)<trunk> - 绝不要手动创建PR。 手动创建的PR不包含版本升级和变更日志。
- 未找到 → 停止操作并报告:"Kein offener Release-PR. Es wurde seit dem letzten Release nichts nach
-
展示即将发布的内容 —— 执行并打印PR标题中的新版本号。询问:"Release
gh pr diff <number> -- CHANGELOG.mdmit diesen Änderungen veröffentlichen?"(是否发布包含这些变更的<version>版本?)等待用户回复。<version> -
检查可合并性 —— 执行
gh pr view <number> --json mergeable,mergeStateStatus- → 继续执行。
MERGEABLE - → 停止操作并报告。不要手动解决版本PR中的冲突——release-please会重新生成它;请在主干上修复冲突原因。
CONFLICTING - → 最多重新轮询3次(每次间隔5秒)。如果仍为
UNKNOWN,报告并停止。UNKNOWN
-
压缩合并 —— 执行
gh pr merge <number> --squash -
监控此次合并触发的运行。 在新运行排队前,仍会返回上一次的发布运行,监控该运行会报告过时的成功状态。将运行与合并提交关联:
gh run list --limit 1bashsha=$(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>
The --close
command
--close--close
命令
--closeDisposes of the current worktree: stops its dev servers, releases its database branch, removes the directory. What it has to do depends on who owns the worktree — check that first.
-
Not a worktree? If the main checkout is the current directory (resolves inside it), there is nothing to close. Report and stop.
git rev-parse --git-common-dir -
Superset-owned worktree — do nothing. The path lives under. Superset runs
~/.superset/worktrees/and removes the worktree when the session closes, so.superset/teardown.shhas no work left. Report that and stop.--closeOnly exception: the user wants the database branch released now while keeping the session open → run the repo's teardown script (— always exits 0, safe to run twice) and leave the directory alone.bash scripts/teardown.sh -
Anywhere else — one command, run from the main checkout:bash
cd "$(git rev-parse --path-format=absolute --git-common-dir)/.." && yarn wt:remove <worktree-path>already chains both halves: it runsworktree-remove.shinside the worktree, thenteardown.sh. Do not callgit worktree removeseparately first.teardown.sh
The repo has to provide those scripts. Check before running — , or in a repo without . Missing → stop and hand the user the setup template in next to this file. Do not improvise a bare : it skips teardown and leaks whatever the worktree held — running dev servers, an undropped database branch.
git grep -q '"wt:remove"' -- package.jsontest -f scripts/worktree-remove.shpackage.jsonWORKTREE-SETUP.mdgit worktree removeTwo things to get right:
- Run it from the main checkout, not from inside the worktree. The command deletes the directory it is pointed at; standing in that directory leaves the shell with no working directory and every later command fails.
- ends the session's work. Nothing can run afterwards — the working tree is gone. Finish everything else first, report, and treat it as the last action.
--close
git worktree remove--forceIt touches no branches. Nothing to delete — GitHub removes the remote branch on merge (), and the local branch goes with the worktree.
delete_branch_on_mergeNever offer unprompted. It is not a step in any workflow — only run it when the user types it. Merging a PR does not call for it.
--closeIf the branch was an — its database branch is shared and outlives the worktree, so teardown leaves it alone. Offer: "Neon-Branch auch löschen? ()". It has no TTL, so nothing removes it on its own. Wait for the answer.
epic/*epic/<name>yarn neon branches delete epic/<name>清理当前工作区:停止开发服务器、释放数据库分支、移除目录。具体操作取决于工作区的所属方——首先检查这一点。
-
不是工作区? 如果当前目录是主检出目录(解析后指向该目录内部),则无需清理。报告并停止。
git rev-parse --git-common-dir -
Superset所属的工作区——无需操作。 路径位于下。Superset会在会话关闭时执行
~/.superset/worktrees/并移除工作区,因此.superset/teardown.sh命令无需执行任何操作。报告此情况并停止。--close唯一例外:用户希望立即释放数据库分支但保持会话打开 → 执行仓库的拆除脚本(——始终返回0,可安全执行两次),并保留目录。bash scripts/teardown.sh -
其他位置——一条命令,从主检出目录执行:bash
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
仓库必须提供这些脚本。 执行前检查——在有的仓库中执行,在没有的仓库中执行。如果缺失 → 停止操作并向用户提供此文件旁的中的设置模板。 不要自行执行裸:它会跳过拆除步骤,导致工作区中的内容泄漏——例如运行中的开发服务器、未删除的数据库分支。
package.jsongit grep -q '"wt:remove"' -- package.jsonpackage.jsontest -f scripts/worktree-remove.shWORKTREE-SETUP.mdgit worktree remove需要注意两点:
- 从主检出目录执行,不要在工作区内部执行。 该命令会删除指向的目录;如果在该目录中执行,会导致Shell失去工作目录,后续所有命令都会失败。
- 命令结束会话的工作。 之后无法执行任何操作——工作区已被移除。先完成所有其他操作,报告结果,并将其视为最后一步操作。
--close
git worktree remove--force不涉及任何分支。 无需删除分支——GitHub会在合并时自动删除远程分支(),本地分支会随工作区一起被移除。
delete_branch_on_merge绝不要主动提供命令。 它不是任何工作流中的步骤——仅当用户输入时才运行。合并PR后无需执行此命令。
--close如果分支是 —— 其数据库分支是共享的,会在工作区移除后继续存在,因此拆除步骤不会处理它。询问用户:"Neon-Branch auch löschen? ()"(是否也删除Neon分支?执行)。该分支没有过期时间,不会自动被移除。等待用户回复。
epic/*epic/<name>yarn neon branches delete epic/<name>epic/<name>yarn neon branches delete epic/<name>The ?
modifier
??
修饰符
?Appending to the end of any shorthand replaces the last action with an inspection instead of execution. All preceding steps in the chain still run normally.
??--cp?r| Last action | |
|---|---|
| Show uncommitted changes: run |
| No-op — nothing useful to show beyond what the commit message already says. Skip silently. |
| Check whether a PR is open for the current branch ( |
| Report the PR's merge state instead of merging: |
| Report how far the branch is behind/ahead of its remote without updating: |
| Inspect the open release PR: version, changelog diff, |
| Report what would be disposed: the worktree path, whether Superset owns it, uncommitted changes, and whether the repo provides |
Examples:
- → summarise uncommitted changes
--c? - → commit, then skip (p? is a no-op)
--cp? - → commit → push → inspect PR status (don't create)
--cppr? - → commit → push → create PR → report merge readiness (don't merge)
--cpprm? - → show how far behind the remote the branch is (don't pull)
--ff? - → show what the next release would contain
--release? - → show what closing would tear down
--close?
在任何简写末尾追加会将最后一步操作替换为检查而非执行。简写中的所有前置步骤仍会正常运行。
??--cp?r| 最后一步操作 | |
|---|---|
| 显示未提交变更:执行 |
| 无操作——除了提交信息外没有有用内容可展示。静默跳过。 |
| 检查当前分支是否已打开PR(执行 |
| 报告PR的合并状态而非执行合并:执行 |
| 报告分支与远程分支的差距但不更新:执行 |
| 检查打开的版本PR:版本号、变更日志差异、 |
| 报告即将清理的内容:工作区路径、是否由Superset所属、未提交变更,以及仓库是否提供 |
示例:
- → 汇总未提交变更
--c? - → 提交,然后跳过(p?无操作)
--cp? - → 提交 → 推送 → 检查PR状态(不创建)
--cppr? - → 提交 → 推送 → 创建PR → 报告可合并性(不合并)
--cpprm? - → 显示分支落后于远程分支的程度(不拉取)
--ff? - → 显示下一个版本将包含的内容
--release? - → 显示清理操作将拆除的内容
--close?