首页
/ Superpowers 实战:用 finishing-a-development-branch 技能规范开发分支的合并、PR 与工作区清理

Superpowers 实战:用 finishing-a-development-branch 技能规范开发分支的合并、PR 与工作区清理

2026-09-04 16:37:34作者:翟萌耘Ralph

本篇技术文章以 Superpowers 框架中的 finishing-a-development-branch 技能文档为主体,完整讲解它在"实现完成、测试通过"这一节点上的标准收尾流程:先验证测试、再检测 git 环境、然后向人类伙伴呈现集成选项、执行选择,最后按"来源归属"原则清理 worktree。读完后你将掌握一套可在任意 Agent 协作开发场景中复用的分支收尾方法论,包括环境检测命令、合并/PR/保留/丢弃四种路径的具体命令序列,以及防止误清理工作区的回归测试验证方式。

技能定位:开发流程的最后一环

在 Superpowers 的技能体系中,finishing-a-development-branch 专门处理"实现已完成、所有测试通过、需要决定如何集成这些工作"的场景(见 SKILL.md 的 frontmatter 描述)。它的核心原则被概括为一句话:

Verify tests → Detect environment → Present options → Execute choice → Clean up. (验证测试 → 检测环境 → 呈现选项 → 执行选择 → 清理)

并且要求在启动时明确宣告:"I'm using the finishing-a-development-branch skill to complete this work."(我正在使用 finishing-a-development-branch 技能完成这项工作)。

从源码结构看,它是整个开发流程图的终点节点:

  • executing-plans 的 Step 3(Complete Development)规定:所有任务完成并验证后,必须宣告并使用 superpowers:finishing-a-development-branch,按其流程验证测试、呈现选项、执行选择;
  • subagent-driven-development 的 Finish 阶段在最终整分支评审(Final Review)通过后,先删除该计划的工作区目录(rm -rf <workspace>,git 历史此时已是唯一记录),随后同样进入 Use superpowers:finishing-a-development-branch
  • README.md 也将它列为标准流程之一:"Activates when tasks complete. Verifies tests, presents options (merge/PR/keep/discard), cleans up worktree."

也就是说,本技能既是"计划执行"和"子代理驱动开发"两条路径的公共收尾出口,也是集成决策权从 Agent 交还给人类伙伴的正式节点。

Step 1: Verify Tests(验证测试)

第一步是运行项目的完整测试套件(npm test / cargo test / pytest / go test ./...),且规则是刚性的:测试失败则报告失败项并停止——选项菜单(menu)只出现在绿色套件之后。文档中给出的报告格式为:

Tests failing (<N> failures). Must fix before completing:

[Show failures]

测试通过才继续进入 Step 2。

这一条对应技能末尾"Common Rationalizations"表中最重要的反驳之一:"Tests passed earlier this session"(本会话早些时候测试是过的)——现实是:必须在你即将集成的这棵树上运行套件。一次绿色运行只能证明它当时运行的那棵树,不能证明合并后的结果。

Step 2: Detect Environment(检测环境)

进入收尾阶段后,先用三条只读 git 命令确定自己处于什么工作区形态:

GIT_DIR=$(cd "$(git rev-parse --git-dir)" 2>/dev/null && pwd -P)
GIT_COMMON=$(cd "$(git rev-parse --git-common-dir)" 2>/dev/null && pwd -P)
# Capture now, while still inside the workspace — Step 5 changes directory
# before cleanup (Step 6) needs this value
WORKTREE_PATH=$(git rev-parse --show-toplevel)

注意注释中的关键细节:WORKTREE_PATH 必须在进入工作区时立刻捕获,因为 Step 5(执行选择)会先改变目录,而 Step 6(清理)要用这个值——不能事后重查。

三个值的组合决定了菜单形态和清理方式:

状态 菜单 清理方式
GIT_DIR == GIT_COMMON(普通仓库) 标准 3 选项 没有 worktree 需要清理
GIT_DIR != GIT_COMMON,命名分支 标准 3 选项 按来源归属处理(见 Step 6)
GIT_DIR != GIT_COMMON,detached HEAD 精简 2 选项(无 merge) 外部托管——原地保留

这套"用 git 原语检测状态、而不是嗅探平台环境变量"的设计来自 Superpowers 的 worktree 重构(rototill)设计文档 2026-04-06-worktree-rototill-design.md。该文档明确了设计原则 Detect state, not platform:用 GIT_DIR != GIT_COMMON 判断"我是否已在 worktree 中",而非检测环境变量识别是哪个 harness——这是 git 2.5(2015 年)起就稳定的原语,跨平台通用,且新 harness 出现时无需维护。设计文档同时解释了为什么 detached HEAD 状态必须去掉 merge 选项:无法从 detached HEAD 发起合并。

using-git-worktrees 的 Step 0 还补充了一个收尾场景同样值得注意的防护——submodule guardGIT_DIR != GIT_COMMON 在 git 子模块内部也为真,所以判断"是否 worktree"前应先执行 git rev-parse --show-superproject-working-tree,有返回路径说明你在子模块而非 worktree,应当作普通仓库处理。codex-tools.md 的平台参考也复用同一组检测命令,并说明 Codex App 沙箱(detached HEAD、外部托管 worktree)下 Agent 应改为提交全部工作后引导用户走 App 的原生"Create branch"/"Hand off to local"控件。

Step 3: Determine Base Branch(确定基础分支)

基础分支就是本次工作所分叉的那个分支——通常已在计划文档、对话上下文或分支的 upstream 中被指明。如果尚不清楚,就问:"This branch split from — is that correct?"(这个分支是从 <你的最佳猜测> 分出来的——对吗?)

文档强调合并前必须确认:合错基础分支的代价是"昂贵到难以撤销"(merging into the wrong base is expensive to undo)。这一条同样出现在 Rationalizations 表里,专门反驳 "The base branch is obviously main"(基础分支显然是 main)这种偷懒推断。

Step 4: Present Options(呈现选项)

菜单必须逐字照写("Present the menu exactly as written"),每个选项都来自文档给出的固定列表;Agent 不得自行增删——尤其是不得主动提供"丢弃"选项(见下节专项说明)。

普通仓库与命名分支 worktree —— 恰好呈现这 3 个选项:

Implementation complete. What would you like to do?

1. Merge back to <base-branch> locally
2. Push and create a Pull Request
3. Keep the branch as-is (I'll handle it later)

Which option?

Detached HEAD —— 恰好呈现这 2 个选项:

Implementation complete. You're on a detached HEAD (externally managed workspace).

1. Push as new branch and create a Pull Request
2. Keep as-is (I'll handle it later)

Which option?

呈现后等待人类回答——集成决策权属于人类伙伴。文档的原文表述是:"Discarding the work happens only in response to your human partner explicitly asking for it."(丢弃工作只会发生在人类伙伴明确提出要求时。)

Step 5: Execute Choice(执行选择)

Option 1: Merge Locally(本地合并)

# Get main repo root for CWD safety
MAIN_ROOT=$(git -C "$(git rev-parse --git-common-dir)/.." rev-parse --show-toplevel)
cd "$MAIN_ROOT"

# Merge first — verify success before removing anything
git checkout <base-branch>
git pull
git merge <feature-branch>

# Verify tests on merged result
<test command>

两个要点值得注意:

  1. CWD 安全:先通过 git-common-dir 反推出主仓库根目录再 cd,因为合并操作必须发生在主仓库而非 worktree 内;
  2. 顺序保证:先合并、验证成功,之后才允许删除任何东西("Merge first — verify success before removing anything")。

合并结果测试失败时:停止,保留 worktree 和分支原样,展开调查——此时还没有任何 push,合并是纯本地的、可恢复的。

合并结果变绿后:先执行 Step 6 清理 worktree,再删除分支:

git branch -d <feature-branch>

Option 2: Push and Create PR(推送并创建 PR)

git push -u origin <feature-branch>
# From a detached HEAD, name the new branch on the remote:
# git push origin HEAD:refs/heads/<new-branch>

随后用托管平台(forge)的工具对 <base-branch> 创建 PR/MR——有 CLI 用 CLI,没有就用多数 forge 在 push 时打印的创建 URL——若仓库存在 PR 模板与约定则遵循,并把 URL 报告给人类伙伴。

保留 worktree——人类伙伴会在该 worktree 里迭代处理 PR 评审反馈。Rationalizations 表专门反驳了 "The PR is up, so the worktree is clutter now"(PR 已经开了,worktree 现在是杂物)这种直觉:"PR feedback gets fixed in that worktree. It stays until the work lands."(PR 反馈就在那个 worktree 里修。它留到工作落地为止。)

Option 3: Keep As-Is(保持原样)

报告一句即可:"Keeping branch . Worktree preserved at

If your human partner asks to discard the work(仅当人类明确要求丢弃)

丢弃路径只作为对明确丢弃请求的响应而存在,且必须先确认——把将永久删除的内容逐项列出:

This will permanently delete:
- Branch <name>
- All commits: <commit-list>
- Worktree at <path>

Type 'discard' to confirm.

等待精确的确认词。文档规定:只有输入的单词 discard 才授权删除——"Yeah, get rid of it" 这类口语化同意不算数。确认到达后:

MAIN_ROOT=$(git -C "$(git rev-parse --git-common-dir)/.." rev-parse --show-toplevel)
cd "$MAIN_ROOT"

然后执行 Step 6 清理 worktree,并强制删除分支:

git branch -D <feature-branch>

注意这里用 git branch -D(强删),区别于 Option 1 中合并完成后的安全删除 git branch -d

Step 6: Cleanup Workspace(清理工作区)

本步只在 Option 1 和已确认的丢弃时运行;Option 2 和 Option 3 永远保留 worktree。两个调用方此时都已 cd 到主仓库根——worktree 移除必须从 worktree 外部执行——并且使用的是 Step 2 中捕获的 GIT_DIR/GIT_COMMON/WORKTREE_PATH 值(在目录改变之前捕获的)。

分三种情况:

情况一:GIT_DIR == GIT_COMMON 普通仓库,没有 worktree 需要清理,结束。

情况二:WORKTREE_PATH 位于 .worktrees/worktrees/ 之下。 Superpowers 自己创建了该 worktree,因此拥有清理权:

git worktree remove "$WORKTREE_PATH"
git worktree prune  # Self-healing: clean up any stale registrations

情况三:其他位置。 宿主环境拥有该工作区——原地保留。若平台提供退出工作区的工具,则使用它。

这里的判定标准就是 rototill 设计文档中的 Provenance-based ownership(来源归属所有权)原则:"Whoever creates the worktree owns its cleanup."(谁创建 worktree,谁负责清理。)Superpowers 创建的(落在 .worktrees/worktrees/ 下)由 Superpowers 清理;harness 创建的(如 .claude/worktrees/~/.codex/worktrees/.gemini/worktrees/)或旧的用户全局路径则一律不碰。

这条所有权边界还有一条可执行的回归测试保障:tests/claude-code/test-worktree-path-policy.sh 会断言 finishing-a-development-branch 技能文件(1)不再提及旧的全局路径 ~/.config/superpowers/worktrees,(2)仍然保留 ".worktrees/ or worktrees/" 的项目本地清理所有权表述,确保重构演进中不会把别人的工作区误删。

Quick Reference(速查表)

选项 合并 推送 保留 Worktree 清理分支
1. 本地合并 yes - - yes
2. 创建 PR - yes yes -
3. 保持原样 - - yes -
丢弃(仅限明确要求) - - - yes(强删)

Common Rationalizations:九种典型越界冲动与纠正

技能文档最有方法论价值的部分,是它预先列举了 Agent 在收尾阶段的九种"合理化借口",并逐条给出事实性纠正。完整继承如下:

借口 现实
"Tests passed earlier this session"(本会话早些时候测试通过过) 在你即将集成的树上运行套件。绿色运行只证明它当时运行过的那棵树。
"They obviously want it merged"(他们显然想合并) 集成是人类伙伴的决定。呈现菜单并等待。
"They seem done with this feature — I'll offer to discard it"(他们好像用完这个功能了——我主动提议丢弃吧) 菜单按原文就是完整的。丢弃只发生在人类伙伴原话提出时。
"'Yeah, get rid of it' counts as confirmation"("是啊,扔了吧"也算确认) 只有输入的单词 discard 授权删除。
"The PR is up, so the worktree is clutter now"(PR 开了,worktree 就是杂物了) PR 反馈就在那个工作区里修。它留到工作落地。
"This other worktree looks stale — I'll clean it too"(另一个 worktree 看起来过期了——顺手清掉) 只清理 .worktrees/worktrees/ 下的 worktree。其余的属于宿主。
"The merged-result failure is probably flaky"(合并结果失败大概是偶发抖动) 合并结果失败就停止一切。分支和 worktree 保持原样直到调查清楚。
"The base branch is obviously main"(基础分支显然是 main) 确认分叉点,或开口问。合错基础分支难以撤销。
"The push was rejected — force-push will fix it"(push 被拒——force-push 能修好) push 被拒意味着远端移动了。先调查;force-push 只在人类伙伴明确要求时进行。

这张表本质上是把"权限边界"写成了可检查的行为规则:测试门禁、决策权归属、确认词字面匹配、清理所有权范围——每一条都可以被测试或评审直接核验。

适用前提与延伸阅读

需要说明的前提:本文所述流程绑定 Superpowers 的技能文档(Markdown 指令文件),它约束的是运行在 Claude Code、Codex、Gemini CLI 等 harness 中的 Agent,而非直接运行给人类的脚本;<base-branch><feature-branch><test command> 等占位符需在具体项目中替换。工作区创建侧的完整规则(同意询问、原生工具优先、git check-ignore 安全检查等)见 skills/using-git-worktrees/SKILL.md;环境检测与 Codex App 沙箱收尾见 skills/using-superpowers/references/codex-tools.md;设计动机与决策记录见 docs/superpowers/specs/2026-04-06-worktree-rototill-design.mddocs/superpowers/plans/2026-04-06-worktree-rototill.md,行为回归测试见 tests/claude-code/test-worktree-path-policy.sh

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
889
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
980
502
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384