Git Worktrees 作为编排原语:在同一仓库中无冲突并行运行 5 个智能体
Git worktrees 解决了任何编排平台都不曾提及的问题:如何在同一仓库中运行多个编码智能体而不互相覆盖工作成果。完整教程,附 bash 别名。
Fabiano Brito
CTO, Autenticare
git worktree 允许 N 个智能体在同一仓库中并行工作,每个智能体拥有独立的分支和工作目录,无文件状态冲突。这是一直藏在你 git 中的编排原语。教程包含 bash 别名及自动清理模式。
并行运行多个编码智能体的经典问题不是算力问题——而是文件状态问题。当你在同一仓库中用 git checkout 启动 5 个并发智能体时,它们都在争抢同一个 git 索引、同一批分支、同一个工作目录。结果是一个任何一个都无法可靠解决的不确定状态。
解决方案在 git 中已存在多年,但大多数工程师从未在生产中使用过它:git worktree。
Addy Osmani 在编码智能体的背景下记录了这一模式。本文超越基础教程,覆盖在生产中真正重要的内容:资源管理、自动清理,以及让工作流顺畅的别名。
Worktree 的技术本质
Worktree 是与同一 git 仓库关联的独立工作目录。每个 worktree:
- 拥有自己的工作树(磁盘上的文件)
- 处于不同的分支(必须如此——两个 worktree 不能在同一分支上)
- 共享同一个
.git/objects(commits、历史、refs) - 在执行期间对其他 worktree 不可见
这意味着每个智能体都有完整的文件状态隔离,同时能访问相同的共享历史。完成后,它推送分支并开启 PR——就像任何人类开发者一样。
# 包含 3 个活跃 worktree 的结构
$ git worktree list
/Users/dev/my-repo abc1234 [main]
/Users/dev/my-repo-feat-a def5678 [auto/feat-a]
/Users/dev/my-repo-feat-b ghi9012 [auto/feat-b]
/Users/dev/my-repo-hotfix jkl3456 [auto/hotfix-login]
每行是一个独立目录,各自运行不同的智能体,零干扰。
为什么这对智能体编排至关重要
编排编码智能体的传统方案通常是以下之一:
- 每个智能体一个仓库 — 开销大,代码共享困难
- 同一仓库的隔离分支加 clone — 可行,但会复制
.git/objects且速度慢 - 顺序执行的智能体 — 放弃了你想要的并行性
Worktrees 是第四种选项:并行、同一仓库、无复制、无冲突。
创建 worktree 的开销极小——本质上是创建一个目录,其中的 HEAD 指向新分支。不复制任何 git 对象。在 worktree 中启动新智能体只需几秒,而非几分钟。
Worktrees 将 git 从版本控制系统转变为智能体的上下文隔离系统。你不是在运行多个 checkout——你是在同一仓库中以有状态安全保证运行多个智能体。
设置:顺畅工作流的 bash 别名
添加到你的 ~/.bashrc 或 ~/.zshrc:
# 为智能体创建 worktree(自动命名规范)
wt-agent() {
local REPO_ROOT
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
if [[ -z "$REPO_ROOT" ]]; then
echo "不在 git 仓库内。" >&2
return 1
fi
local TASK="${1:?用法: wt-agent <任务名>}"
local BRANCH="auto/${TASK}"
local WORKTREE="${REPO_ROOT%/*}/$(basename "$REPO_ROOT")-${TASK}"
git -C "$REPO_ROOT" worktree add "$WORKTREE" -b "$BRANCH"
echo "Worktree 已创建: $WORKTREE (分支: $BRANCH)"
echo "cd $WORKTREE"
}
# 列出活跃 worktree 及概要状态
wt-list() {
git worktree list --porcelain | awk '
/^worktree / { wt=$2 }
/^branch / { br=$2 }
/^HEAD / { hd=substr($2,1,7) }
/^$/ { printf "%-50s %-30s %s\n", wt, br, hd }
'
}
# merge 后移除 worktree 并删除本地分支
wt-clean() {
local TASK="${1:?用法: wt-clean <任务名>}"
local REPO_ROOT
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
local WORKTREE="${REPO_ROOT%/*}/$(basename "$REPO_ROOT")-${TASK}"
local BRANCH="auto/${TASK}"
git worktree remove "$WORKTREE" --force
git branch -d "$BRANCH" 2>/dev/null || echo "本地未找到分支 $BRANCH"
echo "Worktree 和分支已移除: $TASK"
}
# 在 worktree 中启动 Claude Code 智能体(需要 claude CLI)
wt-claude() {
local TASK="${1:?用法: wt-claude <任务名> [提示词]}"
local PROMPT="${2:-}"
local REPO_ROOT
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
local WORKTREE="${REPO_ROOT%/*}/$(basename "$REPO_ROOT")-${TASK}"
if [[ ! -d "$WORKTREE" ]]; then
wt-agent "$TASK"
fi
if [[ -n "$PROMPT" ]]; then
claude --cwd "$WORKTREE" --print "$PROMPT" &
echo "智能体已在后台启动 (PID: $!)"
else
claude --cwd "$WORKTREE"
fi
}
有了这些别名,启动 5 个并行智能体的工作流如下:
# 终端 1 — 重构智能体
wt-claude "refactor-auth" "重构认证模块以使用新的 JWT 提供者"
# 终端 2 — 测试智能体
wt-claude "add-tests-payment" "为支付模块的所有处理器编写单元测试"
# 终端 3 — 文档智能体
wt-claude "update-api-docs" "用 #123 中添加的新端点更新 API 文档"
# 终端 4 — 修复 bug 智能体
wt-claude "fix-session-leak" "修复会话管理中的内存泄漏(issue #456)"
# 终端 5 — 迁移智能体
wt-claude "migrate-db-schema" "编写迁移以在 events 表上添加复合索引"
每条命令在后台启动一个智能体,位于隔离的 worktree 中,处于独立分支上。通过 wt-list 监控进度。
限制与注意事项
Worktrees 解决了文件状态问题,但不能消除所有协调冲突:
Worktrees 无法解决的问题:
- 两个智能体在不同分支上编辑同一文件,PR 中仍会产生合并冲突。
- 数据库锁或外部资源需要外部协调。
- 并发 worktree 的数量上限取决于文件系统——在 NFS 或慢速卷上,每个额外的 worktree 都有真实的 I/O 成本。
最佳实践:
# 创建 worktree 之前,定义明确的文件分区
# 智能体 A: src/auth/**
# 智能体 B: src/payment/**
# 智能体 C: src/notifications/**
# → 无重叠 → 无合并冲突
具有明确文件分区的任务分解在大多数情况下将合并冲突降至近乎为零。
相关文章
主要来源:git-worktree — 官方文档 · Addy Osmani — Code Agent Orchestra
