Learn Claude Code Agent 开发 | 12、目录级隔离:Git Worktree实现多任务并行无冲突
整体概述
s12 是整个系列的收官之作,引入了Git Worktree 目录级任务隔离机制,核心思想来自官方文档:
"各干各的目录, 互不干扰" -- 任务管目标, worktree 管目录, 按 ID 绑定。
Harness 层: 目录隔离 -- 永不碰撞的并行执行通道。
这解决了多智能体并行工作的最后一块短板:工作目录冲突问题。通过控制面(任务)和执行面(工作目录)的分离,实现了多任务并行无干扰,是整个Harness架构的最终形态,完全达到了生产级可用的标准。
解决的核心问题(来自官方文档)
s11 之前共享工作目录的痛点:
- 文件冲突 :两个智能体同时修改同一个文件(比如
config.py),未提交的改动互相覆盖、污染 - 无法回滚:任务失败后,零散的改动无法干净回滚,需要手动清理
- 无法并行:风险操作(比如重构核心模块)只能串行执行,效率低下
- 状态混乱:不同任务的未提交改动混在一起,不知道哪些属于哪个任务
核心架构设计
┌───────────────────────────────────────────────────────────────────┐
│ 控制面(.tasks/) 执行面(.worktrees/) │
├───────────────────────────┐ ┌───────────────────────────────┤
│ task_1.json │ │ auth-refactor/ (独立目录) │
│ id: 1 │ │ 分支: wt/auth-refactor │
│ status: in_progress │ <----> │ 绑定任务ID: 1 │
│ worktree: "auth-refactor"│ │ 所有修改仅在这个目录生效 │
├───────────────────────────┤ ├───────────────────────────────┤
│ task_2.json │ │ ui-login/ (独立目录) │
│ id: 2 │ │ 分支: wt/ui-login │
│ status: pending │ <----> │ 绑定任务ID: 2 │
│ worktree: "ui-login" │ │ 和auth-refactor目录完全隔离 │
└───────────────────────────┘ └───────────────────────────────┘
↓
事件流(.worktrees/events.jsonl)
所有生命周期操作永久记录,可审计、可追溯
状态机:
Task: pending → in_progress → completed
Worktree: absent → active → removed | kept
核心创新:
- 控执分离:任务(控制面)只关心做什么,worktree(执行面)只关心在哪做,通过任务ID双向绑定
- 目录级隔离:每个任务有完全独立的工作目录,基于Git Worktree实现,天然分支隔离
- 完整生命周期:从worktree创建、执行、保留/删除,全流程有状态、有记录
- 可观测性:所有操作都写入事件日志,可追溯、可审计
- 故障可恢复 :崩溃后可以从
.tasks/和.worktrees/index.json重建现场,不会丢失状态
逐段代码解析
1. 仓库根目录检测(第53-71行)
python
def detect_repo_root(cwd: Path) -> Path | None:
"""自动检测Git仓库根目录,支持在子目录中运行"""
try:
r = subprocess.run(
["git", "rev-parse", "--show-toplevel"],
cwd=cwd, capture_output=True, text=True, timeout=10,
)
if r.returncode != 0:
return None
root = Path(r.stdout.strip())
return root if root.exists() else None
except Exception:
return None
REPO_ROOT = detect_repo_root(WORKDIR) or WORKDIR
自动识别Git仓库根目录,保证worktree始终创建在仓库根目录下,不管用户在哪个子目录运行程序。
2. EventBus 事件总线(第82-118行)⭐ 可观测性核心
python
class EventBus:
def __init__(self, event_log_path: Path):
self.path = event_log_path
self.path.parent.mkdir(parents=True, exist_ok=True)
if not self.path.exists():
self.path.write_text("")
def emit(self, event: str, task: dict | None = None, worktree: dict | None = None, error: str | None = None):
"""发送事件,追加到日志文件"""
payload = {
"event": event, "ts": time.time(),
"task": task or {}, "worktree": worktree or {},
}
if error:
payload["error"] = error
with self.path.open("a", encoding="utf-8") as f:
f.write(json.dumps(payload) + "\n")
def list_recent(self, limit: int = 20) -> str:
"""查看最近的事件,用于调试和审计"""
n = max(1, min(int(limit or 20), 200))
lines = self.path.read_text(encoding="utf-8").splitlines()
recent = lines[-n:]
items = []
for line in recent:
try:
items.append(json.loads(line))
except Exception:
items.append({"event": "parse_error", "raw": line})
return json.dumps(items, indent=2)
设计亮点:
- Append-only:事件日志只追加不修改,保证数据不可篡改,可审计
- 全生命周期覆盖:worktree创建前/后/失败、删除前/后/失败、任务完成等所有关键节点都有事件
- 字段丰富:每个事件包含时间戳、关联任务、关联worktree、错误信息等完整上下文
- 可观测性 :通过
worktree_events工具可以查看所有历史操作,出问题可以回溯整个过程
3. TaskManager 升级(第121-217行)
在s07的基础上新增worktree绑定能力:
python
def bind_worktree(self, task_id: int, worktree: str, owner: str = "") -> str:
"""绑定任务和worktree,绑定后自动将任务状态改为in_progress"""
task = self._load(task_id)
task["worktree"] = worktree
if owner:
task["owner"] = owner
if task["status"] == "pending":
task["status"] = "in_progress"
task["updated_at"] = time.time()
self._save(task)
return json.dumps(task, indent=2)
def unbind_worktree(self, task_id: int) -> str:
"""解除任务和worktree的绑定"""
task = self._load(task_id)
task["worktree"] = ""
task["updated_at"] = time.time()
self._save(task)
return json.dumps(task, indent=2)
任务新增 worktree字段,和执行面的worktree一一对应,双向绑定。
4. WorktreeManager 核心类(第224-471行)⭐ 隔离核心
Git Worktree的完整封装,负责worktree的全生命周期管理:
python
def create(self, name: str, task_id: int = None, base_ref: str = "HEAD") -> str:
"""创建新的worktree,可选绑定任务"""
# 1. 校验名称和任务是否存在
# 2. 发送创建前事件
# 3. 执行git worktree add命令,创建独立目录和专属分支
# 4. 更新worktree索引文件
# 5. 绑定任务(如果指定了task_id),自动把任务状态改为in_progress
# 6. 发送创建后事件
核心功能:
- 创建隔离环境:每个worktree是独立的目录,基于指定分支(默认HEAD),有自己的git状态
- 自动绑定任务:创建时指定task_id,自动完成任务和worktree的双向绑定
- 分支命名规范 :所有worktree分支以
wt/为前缀,避免和正常分支混淆
python
def run(self, name: str, command: str) -> str:
"""在指定worktree目录下执行命令,自动切换cwd"""
wt = self._find(name)
path = Path(wt["path"])
r = subprocess.run(
command, shell=True, cwd=path,
capture_output=True, text=True, timeout=300,
)
# ... 返回结果
所有在worktree中执行的命令自动切换工作目录,不需要手动cd,保证操作不会影响其他目录。
python
def remove(self, name: str, force: bool = False, complete_task: bool = False) -> str:
"""删除worktree,可选自动标记关联任务完成"""
# 1. 发送删除前事件
# 2. 执行git worktree remove命令
# 3. 如果complete_task=True,自动把关联任务标记为completed,解除绑定
# 4. 更新索引状态为removed
# 5. 发送删除后事件,同时发送task.completed事件
一站式收尾:删除worktree的同时可以自动完成任务,不需要手动调用任务更新工具。
python
def keep(self, name: str) -> str:
"""保留worktree,不删除,用于需要保留中间结果的场景"""
# 更新索引状态为kept,发送keep事件
支持保留有用的worktree,方便后续检查、调试或者复用。
5. 工具集大升级
相比s11的14个工具,s12新增了大量任务和worktree相关工具,总共16个:
- 任务类:task_create、task_list、task_get、task_update、task_bind_worktree
- Worktree类:worktree_create、worktree_list、worktree_status、worktree_run、worktree_keep、worktree_remove、worktree_events
- 基础工具:bash、read_file、write_file、edit_file
覆盖了从任务创建、worktree分配、执行、收尾的全流程操作。
相对 s11 的变更对比(来自官方文档)
| 组件 | s11(之前) | s12(之后) |
|---|---|---|
| 协调方式 | 仅任务板(owner/status) | 任务板 + worktree 显式双向绑定 |
| 执行范围 | 所有任务共享同一个工作目录 | 每个任务独立的worktree目录,完全隔离 |
| 冲突可能性 | 高,容易互相改同一个文件 | 零冲突,目录完全隔离 |
| 可恢复性 | 仅任务状态持久化 | 任务状态 + worktree索引 + 事件日志,可完全重建 |
| 收尾流程 | 仅标记任务完成 | 显式选择worktree保留/删除,自动完成关联任务 |
| 可观测性 | 隐式日志,无标准记录 | events.jsonl显式事件流,全生命周期可审计 |
| 并行支持 | 低,容易冲突 | 高,任意数量任务并行无干扰 |
使用示例(来自文档)
bash
python agents/Worktree目录隔离核心实现
# 1. 创建两个任务
s12 >> Create tasks: "重构auth模块", "开发登录页面"
> task_create: 创建任务1和任务2成功
s12 >> /tasks
[ ] #1: 重构auth模块
[ ] #2: 开发登录页面
# 2. 分别绑定worktree
s12 >> Create worktree "auth-refactor" for task 1
> worktree_create: 创建worktree auth-refactor,绑定任务1,任务状态变为in_progress
s12 >> Create worktree "ui-login" for task 2
> worktree_create: 创建worktree ui-login,绑定任务2,任务状态变为in_progress
s12 >> /worktrees
[active] auth-refactor -> .worktrees/auth-refactor (wt/auth-refactor) task=1
[active] ui-login -> .worktrees/ui-login (wt/ui-login) task=2
# 3. 在各自的worktree中执行命令,互不干扰
s12 >> Run "echo 'auth v2' > auth.py" in worktree "auth-refactor"
> worktree_run: 执行成功,只修改auth-refactor目录下的auth.py,不影响主目录和ui-login目录
s12 >> Run "echo 'login page' > login.html" in worktree "ui-login"
> worktree_run: 执行成功,只修改ui-login目录下的login.html
# 4. 收尾
s12 >> Remove worktree "auth-refactor" with complete_task=true
> worktree_remove: 删除auth-refactor目录,任务1自动标记为completed
s12 >> Keep worktree "ui-login" # 保留这个worktree后续调试用
> worktree_keep: 标记ui-login为kept状态
# 5. 查看事件日志
s12 >> worktree_events
[
{"event": "worktree.create.after", "ts": 1730000000, "worktree": {"name": "auth-refactor"}, "task": {"id": 1}},
{"event": "worktree.create.after", "ts": 1730000010, "worktree": {"name": "ui-login"}, "task": {"id": 2}},
{"event": "task.completed", "ts": 1730000100, "task": {"id": 1, "status": "completed"}},
{"event": "worktree.remove.after", "ts": 1730000100, "worktree": {"name": "auth-refactor", "status": "removed"}},
{"event": "worktree.keep", "ts": 1730000110, "worktree": {"name": "ui-login", "status": "kept"}}
]
核心设计思想和收获
s12 完成了整个Harness架构的最终闭环,是整个系列的集大成之作:
1. 控执分离架构
控制面(任务)和执行面(worktree)完全分离,通过ID关联,职责清晰,扩展性极强。控制面可以替换成其他任务管理系统,执行面也可以替换成Docker容器等其他隔离方式。
2. 零冲突并行
基于Git Worktree的目录级隔离,完美解决了多智能体并行工作的冲突问题,支持任意数量的任务同时执行,互不干扰。
3. 生产级可观测性
全生命周期事件流,所有操作有记录、可审计、可回溯,出问题可以完整复现整个过程。
4. 故障自愈能力
所有状态都持久化在磁盘,程序崩溃、服务器重启都可以从文件重建现场,不会丢失任务进度。
5. 完整的生命周期管理
从任务创建、资源分配、执行、收尾,全流程有标准工具和规范,不需要人工干预。
整个系列从s01的最简单循环,到s12的完整生产级多智能体并行架构,完美体现了Harness层的设计哲学:模型做决策,Harness层提供环境、工具、隔离、协调、可观测性,让模型可以专注于最擅长的推理工作,其他所有工程性问题都由Harness层解决。
本内容参考开源项目 learn-claude-code