Skip to content

Commit 473b011

Browse files
authored
chore(skills): 同步上游 v5.1.0 worktree 安全修复(issue #19 第一批) (#28)
把 upstream/main v5.1.0 在 using-git-worktrees + finishing-a-development-branch 两个 skill 上的行为变更逐字翻译同步过来。属于上游修复 obra/superpowers#991 (subagent 自动创建嵌套 worktree、清理误删 harness-managed workspace)。 using-git-worktrees: - 新增 Step 0:GIT_DIR vs GIT_COMMON 检测现有隔离,submodule 守卫 - 新增创建前同意流程(除非 instructions 已声明偏好) - 重组 Step 1 为 1a Native Tools (首选) + 1b Git Worktree Fallback - 新增沙盒回退(permission error 时原地工作) - 删除旧"示例工作流"段(含 /Users/jesse 硬编码路径) - 保留章节编号 Step 1→3 的上游怪癖(不擅自"修正") finishing-a-development-branch: - 新增 Step 2 检测环境(三态表决定菜单形态和清理逻辑) - 旧 Step 2/3/4/5 重编号为 3/4/5/6 - Step 4 新增分离 HEAD 3 选项变体 - Step 5 Option 1 重写:MAIN_ROOT cwd safety + merge→verify→cleanup→delete 严格排序 - Step 5 Option 2 增加 "Do NOT cleanup worktree" 提示(PR 迭代需要) - Step 6 清理范围限定:只清 .worktrees/ / worktrees/ / ~/.config/superpowers/worktrees/ 之内的;外部 harness-managed workspace 一律不动(核心安全修复) - 红线 + 常见错误段扩展(按上游对应同步) 翻译原则: - 章节标题翻译,但保留章节编号 (Step 0/1/3/4 一一对应) - 代码块完全保留,不翻译变量名/命令 - 散文逐句翻译,不简化不扩写 - 我们独有的 "## 集成" 段保留(指向 brainstorming/subagent-driven-development 等) 不属于本 PR 范围: - review loop 简化(v5.0.6 brainstorming/writing-plans)→ 下一批 - code-reviewer 整合(v5.1.0 requesting-code-review)→ 下一批 - subagent 节奏调整 (v5.1.0 subagent-driven-development) → 下一批 - brainstorm server.cjs 脚本结构同步 (v5.0.6 CONTENT_DIR/STATE_DIR) → 单独 PR Refs: #19
1 parent 132b658 commit 473b011

2 files changed

Lines changed: 221 additions & 129 deletions

File tree

skills/finishing-a-development-branch/SKILL.md

Lines changed: 107 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ description: 当实现完成、所有测试通过、需要决定如何集成工
99

1010
通过提供清晰的选项并执行所选工作流来引导开发工作的收尾。
1111

12-
**核心原则:** 验证测试 → 展示选项 → 执行选择 → 清理。
12+
**核心原则:** 验证测试 → 检测环境 → 展示选项 → 执行选择 → 清理。
1313

1414
**开始时宣布:** "我正在使用 finishing-a-development-branch 技能来完成这项工作。"
1515

@@ -25,6 +25,7 @@ npm test / cargo test / pytest / go test ./...
2525
```
2626

2727
**如果测试失败:**
28+
2829
```
2930
测试失败(<N> 个失败)。必须先修复才能继续:
3031
@@ -37,7 +38,24 @@ npm test / cargo test / pytest / go test ./...
3738

3839
**如果测试通过:** 继续步骤 2。
3940

40-
### 步骤 2:确定基础分支
41+
### 步骤 2:检测环境
42+
43+
**在展示选项之前,先确定工作区状态:**
44+
45+
```bash
46+
GIT_DIR=$(cd "$(git rev-parse --git-dir)" 2>/dev/null && pwd -P)
47+
GIT_COMMON=$(cd "$(git rev-parse --git-common-dir)" 2>/dev/null && pwd -P)
48+
```
49+
50+
这决定了展示哪种菜单、以及清理方式:
51+
52+
| 状态 | 菜单 | 清理 |
53+
|------|------|------|
54+
| `GIT_DIR == GIT_COMMON`(普通仓库) | 标准 4 个选项 | 无 worktree 可清理 |
55+
| `GIT_DIR != GIT_COMMON`,命名分支 | 标准 4 个选项 | 按来源判断(见步骤 6) |
56+
| `GIT_DIR != GIT_COMMON`,分离 HEAD | 收敛 3 个选项(无合并) | 无清理(由外部管理) |
57+
58+
### 步骤 3:确定基础分支
4159

4260
```bash
4361
# 尝试常见的基础分支
@@ -46,9 +64,9 @@ git merge-base HEAD main 2>/dev/null || git merge-base HEAD master 2>/dev/null
4664

4765
或者询问:"这个分支是从 main 分出来的——对吗?"
4866

49-
### 步骤 3:展示选项
67+
### 步骤 4:展示选项
5068

51-
展示以下 4 个选项:
69+
**普通仓库和命名分支 worktree —— 准确展示以下 4 个选项:**
5270

5371
```
5472
实现已完成。你想怎么做?
@@ -61,30 +79,45 @@ git merge-base HEAD main 2>/dev/null || git merge-base HEAD master 2>/dev/null
6179
选哪个?
6280
```
6381

64-
**不要添加解释** - 保持选项简洁。
82+
**分离 HEAD —— 准确展示以下 3 个选项:**
83+
84+
```
85+
实现已完成。你在分离 HEAD 上(由外部管理的工作区)。
86+
87+
1. 作为新分支推送并创建 Pull Request
88+
2. 保持现状(我稍后处理)
89+
3. 丢弃这项工作
90+
91+
选哪个?
92+
```
93+
94+
**不要添加解释** —— 保持选项简洁。
6595

66-
### 步骤 4:执行选择
96+
### 步骤 5:执行选择
6797

6898
#### 选项 1:本地合并
6999

70100
```bash
71-
# 切换到基础分支
72-
git checkout <base-branch>
101+
# 切到主仓库根目录,保证 CWD 安全
102+
MAIN_ROOT=$(git -C "$(git rev-parse --git-common-dir)/.." rev-parse --show-toplevel)
103+
cd "$MAIN_ROOT"
73104

74-
# 拉取最新代码
105+
# 先合并 —— 在删除任何东西之前先验证合并成功
106+
git checkout <base-branch>
75107
git pull
76-
77-
# 合并功能分支
78108
git merge <feature-branch>
79109

80110
# 在合并结果上验证测试
81111
<test command>
82112

83-
# 如果测试通过
84-
git branch -d <feature-branch>
113+
# 合并成功之后再:清理 worktree(步骤 6),然后删除分支
85114
```
86115

87-
然后:清理工作树(步骤 5)
116+
然后:清理 worktree(步骤 6),再删除分支:
117+
118+
```bash
119+
git branch -d <feature-branch>
120+
```
88121

89122
#### 选项 2:推送并创建 PR
90123

@@ -103,7 +136,7 @@ EOF
103136
)"
104137
```
105138

106-
然后:清理工作树(步骤 5)
139+
**不要清理 worktree** —— 用户在 PR 反馈迭代时还需要它存活。
107140

108141
#### 选项 3:保持现状
109142

@@ -114,6 +147,7 @@ EOF
114147
#### 选项 4:丢弃
115148

116149
**先确认:**
150+
117151
```
118152
这将永久删除:
119153
- 分支 <name>
@@ -126,28 +160,40 @@ EOF
126160
等待精确的确认。
127161

128162
确认后:
163+
129164
```bash
130-
git checkout <base-branch>
131-
git branch -D <feature-branch>
165+
MAIN_ROOT=$(git -C "$(git rev-parse --git-common-dir)/.." rev-parse --show-toplevel)
166+
cd "$MAIN_ROOT"
132167
```
133168

134-
然后:清理工作树(步骤 5)
169+
然后:清理 worktree(步骤 6),再强制删除分支:
170+
171+
```bash
172+
git branch -D <feature-branch>
173+
```
135174

136-
### 步骤 5:清理工作树
175+
### 步骤 6:清理工作区
137176

138-
**对于选项 1、2、4:**
177+
**只对选项 1 和 4 执行。** 选项 2 和 3 始终保留 worktree。
139178

140-
检查是否在工作树中:
141179
```bash
142-
git worktree list | grep $(git branch --show-current)
180+
GIT_DIR=$(cd "$(git rev-parse --git-dir)" 2>/dev/null && pwd -P)
181+
GIT_COMMON=$(cd "$(git rev-parse --git-common-dir)" 2>/dev/null && pwd -P)
182+
WORKTREE_PATH=$(git rev-parse --show-toplevel)
143183
```
144184

145-
如果是:
185+
**如果 `GIT_DIR == GIT_COMMON`** 普通仓库,无 worktree 可清理。结束。
186+
187+
**如果 worktree 路径在 `.worktrees/``worktrees/``~/.config/superpowers/worktrees/` 之下:** 这是 Superpowers 创建的 worktree —— 我们负责清理。
188+
146189
```bash
147-
git worktree remove <worktree-path>
190+
MAIN_ROOT=$(git -C "$(git rev-parse --git-common-dir)/.." rev-parse --show-toplevel)
191+
cd "$MAIN_ROOT"
192+
git worktree remove "$WORKTREE_PATH"
193+
git worktree prune # 自愈:清理任何过期的注册记录
148194
```
149195

150-
**对于选项 3** 保留工作树
196+
**否则** 这个工作区由宿主环境(harness)管理。**不要**移除它。如果你的平台提供了工作区退出工具,用它。否则原样保留工作区
151197

152198
## 快速参考
153199

@@ -161,40 +207,69 @@ git worktree remove <worktree-path>
161207
## 常见错误
162208

163209
**跳过测试验证**
210+
164211
- **问题:** 合并损坏的代码、创建失败的 PR
165212
- **修复:** 在提供选项前始终验证测试
166213

167214
**开放式问题**
215+
168216
- **问题:** "接下来该做什么?" → 含糊不清
169-
- **修复:** 准确展示 4 个结构化选项
217+
- **修复:** 准确展示 4 个结构化选项(分离 HEAD 时是 3 个)
218+
219+
**为选项 2 清理 worktree**
170220

171-
**自动清理工作树**
172-
- **问题:** 在可能还需要工作树时就删除了(选项 2、3)
221+
- **问题:** 删掉用户 PR 迭代还需要的 worktree
173222
- **修复:** 只在选项 1 和 4 时清理
174223

224+
**先删分支再删 worktree**
225+
226+
- **问题:** `git branch -d` 失败,因为 worktree 还引用着该分支
227+
- **修复:** 先合并,再删 worktree,最后删分支
228+
229+
**在 worktree 内部跑 `git worktree remove`**
230+
231+
- **问题:** 当 CWD 在被删除的 worktree 内时,命令静默失败
232+
- **修复:**`git worktree remove` 前先 `cd` 到主仓库根目录
233+
234+
**清理 harness 拥有的 worktree**
235+
236+
- **问题:** 移除 harness 创建的 worktree 会造成幻影状态
237+
- **修复:** 只清理 `.worktrees/``worktrees/``~/.config/superpowers/worktrees/` 下的 worktree
238+
175239
**丢弃时不确认**
240+
176241
- **问题:** 意外删除工作成果
177-
- **修复:** 要求输入 "discard" 确认
242+
- **修复:** 要求输入 'discard' 确认
178243

179244
## 红线
180245

181246
**绝不:**
247+
182248
- 在测试失败时继续
183-
- 合并前不验证测试结果
249+
- 合并前不验证合并结果上的测试
184250
- 不确认就删除工作成果
185251
- 未经明确请求就强制推送
252+
- 在确认合并成功之前移除 worktree
253+
- 清理不是你创建的 worktree(按来源判断)
254+
- 在 worktree 内部跑 `git worktree remove`
186255

187256
**始终:**
257+
188258
- 在提供选项前验证测试
189-
- 准确展示 4 个选项
259+
- 展示菜单前检测环境
260+
- 准确展示 4 个选项(分离 HEAD 时是 3 个)
190261
- 选项 4 要求输入确认
191-
- 只在选项 1 和 4 时清理工作树
262+
- 只在选项 1 和 4 时清理 worktree
263+
- 移除 worktree 前 `cd` 到主仓库根目录
264+
- 移除后跑 `git worktree prune`
192265

193266
## 集成
194267

195268
**被以下技能调用:**
269+
196270
- **subagent-driven-development**(步骤 7)- 所有任务完成后
197271
- **executing-plans**(步骤 5)- 所有批次完成后
198272

199273
**配合使用:**
274+
200275
- **using-git-worktrees** - 清理由该技能创建的工作树

0 commit comments

Comments
 (0)