用途
该技能用于开发分支的收尾阶段。当你的实现已完成、所有测试通过、需要决定如何整合这部分工作时使用它。技能在开始时应当宣告:"I'm using the finishing-a-development-branch skill to complete this work."
核心原则为:验证测试 → 检测环境 → 呈现选项 → 执行选择 → 清理。
主要流程
第一步:验证测试
运行项目完整的测试套件(npm test / cargo test / pytest / go test ./...)。如果测试失败,报告失败并停止——选项菜单在测试套件变绿之后才出现:
Tests failing (<N> failures). Must fix before completing:
[Show failures]
如果测试通过,继续第二步。
第二步:检测环境
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)
这决定了显示哪个菜单以及清理如何执行:
| 状态 | 菜单 | 清理 |
|---|---|---|
| GIT_DIR == GIT_COMMON(普通仓库) | 标准 3 个选项 | 无工作树可清理 |
| GIT_DIR != GIT_COMMON,命名分支 | 标准 3 个选项 | 基于来源(见第六步) |
| GIT_DIR != GIT_COMMON,分离 HEAD | 精简 2 个选项(无合并) | 外部管理——保持原位 |
第三步:确定基分支
基分支是这次工作从哪个分支分叉出来的——通常会在计划、对话或分支的上游中说明。如果尚不清楚,询问:"This branch split from - is that correct?"。合并前务必确认:合并到错误的基分支代价高昂且难以撤销。
第四步:呈现选项
普通仓库与命名分支工作树——恰好呈现以下 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?
分离 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?
严格按原文呈现菜单——简洁,且每个选项都来自上述列表。丢弃工作仅在人类伙伴明确要求时才发生。等待对方回答;整合决策属于他们。
第五步:执行选择
选项 1:本地合并
# 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>
如果合并结果的测试失败:停止,保留工作树与分支不变,进行调查——尚未推送,所以合并是本地且可恢复的。
合并结果一旦变绿:清理工作树(第六步),然后删除分支:
git branch -d <feature-branch>
选项 2:推送并创建 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>
然后用代码托管平台的工具对目标创建 pull/merge request——若有 CLI 则用它,否则用推送时多数平台打印的创建 URL——若仓库存在 PR 模板与约定则遵循之,并向人类伙伴报告 URL。保留工作树——人类伙伴会在那里迭代处理 PR 反馈。
选项 3:保持现状
报告:"Keeping branch . Worktree preserved at ."
如果人类伙伴要求丢弃工作
该路径仅作为明确要求丢弃工作的响应而存在。首先确认:
This will permanently delete:
- Branch <name>
- All commits: <commit-list>
- Worktree at <path>
Type 'discard' to confirm.
等待这一确切确认。收到后:
MAIN_ROOT=$(git -C "$(git rev-parse --git-common-dir)/.." rev-parse --show-toplevel)
cd "$MAIN_ROOT"
然后清理工作树(第六步)并强制删除分支:
git branch -D <feature-branch>
第六步:清理工作区
在选项 1 和已确认的丢弃时运行。选项 2 与选项 3 始终保留工作树。两个调用方都已切换目录到主仓库根目录——工作树移除必须在工作树之外运行——并使用第二步捕获的 GIT_DIR/GIT_COMMON/WORKTREE_PATH 值(在目录切换之前捕获)。
如果 GIT_DIR == GIT_COMMON:普通仓库,无工作树可清理。完成。
如果 WORKTREE_PATH 位于 .worktrees/ 或 worktrees/ 下:该工作树由 Superpowers 创建——由我们负责清理:
git worktree remove "$WORKTREE_PATH"
git worktree prune # Self-healing: clean up any stale registrations
如果移除被拒绝(包含已修改或未跟踪文件):该工作树持有其他任何地方都不存在的文件——未提交的计划、笔记或草稿工作。绝不可主动使用 --force。向人类伙伴展示风险并询问:
git -C "$WORKTREE_PATH" status --porcelain -uall
Worktree removal refused — these files were never committed:
<file list>
1. Commit them to <branch> before cleanup
2. Move them into <main repo root>
3. Delete them (unrecoverable)
Which?
执行所选操作,然后移除工作树。
否则:宿主环境拥有该工作区——保持原位。如果你的平台提供退出工作区的工具,使用它。
快速参考
| 选项 | 合并 | 推送 | 保留工作树 | 清理分支 |
|---|---|---|---|---|
| 1. 本地合并 | 是 | - | - | 是 |
| 2. 创建 PR | - | 是 | 是 | - |
| 3. 保持现状 | - | - | 是 | - |
| 丢弃(仅限明确要求) | - | - | - | 是(强制) |
常见的自我合理化
| 借口 | 现实 |
|---|---|
| "本次会话中测试之前已通过" | 在你即将整合的那棵树上运行测试套件。一次绿测仅证明它当时运行的那棵树。 |
| "他们显然希望合并" | 整合是人类伙伴的决定。呈现菜单并等待。 |
| "他们似乎已经完成这个功能——我来提议丢弃它" | 菜单按原文即为完整。仅当人类伙伴明确要求时才丢弃。 |
| "'Yeah, get rid of it' 也算确认" | 只有键入的 discard 一词才授权删除。 |
| "PR 已经开了,工作树现在是杂物" | PR 反馈就在那个工作树里修复。它会一直保留到工作落地。 |
| "这个其他工作树看起来过时了——我也一并清理" | 只清理 .worktrees/ 或 worktrees/ 下的工作树。其他一切归宿主所有。 |
| "移除被拒绝——--force 只是完成清理" | 被拒绝意味着文件仅存在于该工作树。--force 会永久销毁它们。展示给人类伙伴并询问。 |
| "合并结果的失败可能是偶发" | 合并结果失败将停止一切。分支与工作树保持原位,直到你调查清楚。 |
| "基分支显然是 main" | 确认分叉点或询问。合并到错误的基分支代价高昂且难以撤销。 |
| "推送被拒绝——force-push 能解决" | 推送被拒绝意味着远端已移动。调查;仅在人类伙伴明确要求时才 force-push。 |