使用 Git Worktrees
概述
确保工作发生在隔离工作区中。优先使用你所在平台的原生 worktree 工具。仅当没有可用的原生工具时,才回退到手动 git worktree。
核心原则: 首先检测现有隔离。然后使用原生工具。然后回退到 git。禁止与 harness 对抗。
开始时宣布: “我正在使用 using-git-worktrees 技能来设置隔离工作区。”
步骤 0:检测现有隔离
在创建任何内容之前,检查你是否已经处于隔离工作区。
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)
BRANCH=$(git branch --show-current)
子模块防护: 在 git 子模块内,GIT_DIR != GIT_COMMON 也成立。在得出“已经在 worktree 中”的结论之前,验证你不在子模块中:
# If this returns a path, you're in a submodule, not a worktree — treat as normal repo
git rev-parse --show-superproject-working-tree 2>/dev/null
如果 GIT_DIR != GIT_COMMON(且不是子模块): 你已经位于一个链接的 worktree 中。跳到步骤 2(项目设置)。禁止再创建另一个 worktree。
按分支状态报告:
- 在分支上:“已在位于
<path>的隔离工作区中,分支为<name>。” - 分离 HEAD:“已在位于
<path>的隔离工作区中(分离 HEAD,由外部管理)。完成时需要创建分支。”
如果 GIT_DIR == GIT_COMMON(或在子模块中): 你位于一个普通仓库检出中。
用户是否已在你的指令中表明其 worktree 偏好?如果没有,在创建 worktree 之前征求同意:
“你希望我设置一个隔离的 worktree 吗?它可以保护你当前分支免受更改影响。”
尊重任何已经声明的偏好,不再询问。如果用户拒绝同意,就地工作并跳到步骤 2。
步骤 1:创建隔离工作区
你有两种机制。按此顺序尝试。
1a. 原生 Worktree 工具(首选)
用户已请求隔离工作区(步骤 0 同意)。你是否已经有创建 worktree 的方式?它可能是名为 EnterWorktree、WorktreeCreate 的工具、/worktree 命令或 --worktree 标志。如果有,使用它并跳到步骤 2。
原生工具会自动处理目录放置、分支创建和清理。当你拥有原生工具时使用 git worktree add 会创建你的 harness 无法看到或管理的幻影状态。
仅当你没有可用的原生 worktree 工具时,才继续步骤 1b。
1b. Git Worktree 回退
仅当步骤 1a 不适用时使用此方法 —— 你没有可用的原生 worktree 工具。使用 git 手动创建 worktree。
目录选择
遵循以下优先级顺序。明确的用户偏好始终胜过观察到的文件系统状态。
- 检查你的指令中是否声明了 worktree 目录偏好。 如果用户已经指定,使用它,不要询问。
- 检查是否存在项目本地的 worktree 目录:
``bash ls -d .worktrees 2>/dev/null # Preferred (hidden) ls -d worktrees 2>/dev/null # Alternative ` 如果找到,使用它。如果两者都存在,.worktrees` 优先。
- 如果没有其他可用指导,默认在项目根目录使用
.worktrees/。
安全验证(仅限项目本地目录)
在创建 worktree 之前,必须验证目录已被忽略:
git check-ignore -q .worktrees 2>/dev/null || git check-ignore -q worktrees 2>/dev/null
如果未被忽略: 添加到 .gitignore,提交更改,然后继续。
为何关键: 防止意外将 worktree 内容提交到仓库。
创建 Worktree
# Determine path based on chosen location
path="$LOCATION/$BRANCH_NAME"
git worktree add "$path" -b "$BRANCH_NAME"
cd "$path"
沙箱回退: 如果 git worktree add 因权限错误(沙箱拒绝)失败,告诉用户沙箱阻止了 worktree 创建,你改为在当前目录工作。然后就地运行设置和基线测试。
步骤 2:项目设置
自动检测并运行适当设置:
# Node.js
if [ -f package.json ]; then npm install; fi
# Rust
if [ -f Cargo.toml ]; then cargo build; fi
# Python
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
if [ -f pyproject.toml ]; then poetry install; fi
# Go
if [ -f go.mod ]; then go mod download; fi
步骤 3:验证干净基线
运行测试以确保工作区以干净状态开始:
# Use project-appropriate command
npm test / cargo test / pytest / go test ./...
如果测试失败: 报告失败,询问是继续还是调查。
如果测试通过: 报告就绪。
报告
Worktree ready at <full-path>
Tests passing (<N> tests, 0 failures)
Ready to implement <feature-name>
快速参考
| 情况 | 操作 | |-----------|--------| | 已在链接 worktree 中 | 跳过创建(步骤 0) | | 在子模块中 | 按普通仓库处理(步骤 0 防护) | | 原生 worktree 工具可用 | 使用它(步骤 1a) | | 没有原生工具 | Git worktree 回退(步骤 1b) | | .worktrees/ 存在 | 使用它(验证已忽略) | | worktrees/ 存在 | 使用它(验证已忽略) | | 两者都存在 | 使用 .worktrees/ | | 两者都不存在 | 检查指令文件,然后默认 .worktrees/ | | 目录未被忽略 | 添加到 .gitignore + 提交 | | 创建时权限错误 | 沙箱回退,就地工作 | | 基线期间测试失败 | 报告失败 + 询问 | | 没有 package.json/Cargo.toml | 跳过依赖安装 |
常见合理化借口
| 借口 | 现实 | |--------|---------| | “我显然不在 worktree 中——无需检查” | 运行步骤 0。harness 创建的隔离和子模块都会骗过肉眼;检测命令会确定。 | | “git worktree add 比寻找原生工具更快” | 原生工具(例如 EnterWorktree)拥有放置、分支和清理。绕过它是 #1 错误——它会创建你的 harness 无法看到或管理的幻影状态。 | | “worktree 目录肯定已经被忽略了” | 运行 git check-ignore。未忽略的 worktree 目录会把整棵树提交到仓库。 | | “任何目录名都可以” | 明确指令胜过现有项目本地目录,后者胜过 .worktrees/ 默认值。 | | “工作区是新的——基线测试可以等待” | 脏基线会让之后每次失败都含糊不清。现在运行测试;越过失败继续是你人类伙伴的决定。 |