Skip to content

用 git worktree 并行运行多个编码智能体

SuperDevSpace 如何在同一个仓库里隔离多个编码智能体:每个 worker 独立的 git worktree 和分支、每轮自动提交、squash merge 合并。

作者:SuperDevSpace

发布于 阅读约 7 分钟

其他语言: English Türkçe Deutsch Français Español Português (Brasil) 日本語

SuperDevSpace 中 manager 真实的 Claude Code 终端正在应用一行修改,并以 diff 显示

在同一份检出里同时跑两个编码智能体,你很快就会明白软件团队为什么要用分支。一个智能体正在给模块改名,另一个却拿改了一半的代码去跑测试。一个把另一个刚删掉的文件加进了暂存区。它们谁都没错,只是共用了一张桌子。

SuperDevSpace 会在同一个仓库里同时运行一个 manager 和多个 worker。本文介绍让它们彼此隔离的机制——git worktree——以及应用围绕它遵守的具体规则。

什么是 git worktree

一个 git 仓库通常只有一个工作目录。git worktree 让同一个仓库拥有多个工作目录,每个检出在自己的分支上,所有目录共享同一个对象库。没有第二个克隆,也没有第二份历史:新建一个 worktree 只占用一份检出的文件,别无其他。

你可以在任何仓库里手动试一试。命令在哪儿都一样,只是 shell 不同:

macOS / Linux

终端
git worktree add -b agent/frontend-demo ../myrepo-frontend
git worktree list
cd ../myrepo-frontend && git status
cd - && git worktree remove ../myrepo-frontend

Windows (PowerShell)

终端
git worktree add -b agent/frontend-demo ..\myrepo-frontend
git worktree list
cd ..\myrepo-frontend; git status
cd ..\myrepo; git worktree remove ..\myrepo-frontend

每个 worktree 都有自己的 HEAD、自己的索引和自己的文件。两个进程可以同时在两个 worktree 里编辑、构建和测试,互相看不到对方改到一半的内容。这正是一支智能体团队需要的特性。

SuperDevSpace 如何使用它们

规则很简单,对每个组织都一样:

  • manager 在你的主检出里工作。 它负责规划、审查和合并;那是各分支汇合的唯一地方。
  • 每个 worker 在自己的分支上拥有自己的 worktree。 manager 招聘 worker 时,应用会为它运行 git worktree add -b <branch> <path>。除非你自己命名,分支名为 agent/<worker 名>-<时间戳>。
  • worktree 存放在应用自己的数据目录里,位于 worktrees/<组织>/<worker> 下,绝不放进你的仓库。你的项目文件夹不会被智能体的目录塞满。
  • 每一轮都会提交。 worker 完成一轮后,应用会把它 worktree 里的所有改动提交(agent(<name>): turn)。worker 做过的任何事,都不会只停留在未提交的工作目录里。
  • 合并采用 squash merge。 manager 接受某个 worker 的报告后,分支会通过 git merge --squash 以一个提交并入你的主线。如果合并冲突,应用会中止合并,把仓库恢复干净以便下一步操作,而不是把你丢在冲突的合并中间。
  • 每个仓库同一时间只执行一个 git 操作。 worktree 目录隔离了文件;每个仓库一条队列,把 git 命令本身串行化,所以两个 worker 同时完成时,也不会争抢 git 的元数据。
两个 worker、两条分支、两次 squash merge两个 worker、两条分支、两次 squash merge
两个 worker、两条分支、两次 squash merge
以文本查看图表
gitGraph
  commit id: "main"
  branch agent/frontend
  commit id: "frontend: 第 1 轮"
  checkout main
  branch agent/qa
  commit id: "qa: 第 1 轮"
  checkout agent/frontend
  commit id: "frontend: 第 2 轮"
  checkout main
  merge agent/frontend id: "squash: frontend"
  merge agent/qa id: "squash: qa"

在看板上,这表现为几项任务同时在推进,每项属于不同的 worker,每项下面都有自己的分支。

一个冲刺看板,任务分布在待做、进行中、待审批、审查中和已完成等列
组织看板上并行推进的任务——每个 worker 都在自己的分支上(真实应用,界面为土耳其语)。

让它真正好用的细节

新建的 worktree 只包含 git 跟踪的文件。这通常不足以把项目跑起来:node_modules、本地的 .env、生成的文件都没有。下面两个细节解决了这个问题。

每个仓库一个初始化脚本

如果你的仓库里有 .super/scripts/setup-worktree.sh,应用会在 worker 启动前,在每个新 worktree 里运行它,并用 SUPERDEV_MAIN_REPO 指向你的主检出。它的输出会实时显示,漫长的安装不再是盲等,而且你可以随时取消。

.super/scripts/setup-worktree.sh
#!/usr/bin/env bash
set -euo pipefail
# 从主检出复制仅存在于本地的文件
cp "$SUPERDEV_MAIN_REPO/.env" .env 2>/dev/null || true
# 安装依赖(pnpm 从共享存储建立链接,所以很快)
pnpm install --frozen-lockfile

子模块

git worktree add 不会填充子模块。如果新 worktree 里有 .gitmodules 文件,应用会在其中运行 git submodule update --init --recursive,避免 worker 在悄悄缺失依赖的情况下构建。

清理时不丢失工作

worktree 会越积越多。应用会回收它们,但非常谨慎:

什么时候可以删除 worker 的 worktree什么时候可以删除 worker 的 worktree
什么时候可以删除 worker 的 worktree
以文本查看图表
flowchart TD
  start["worker 已完成"] --> clean{"工作区干净吗?"}
  clean -->|"否"| keep["保留 worktree"]
  clean -->|"是"| merged{"分支已并入你的主线?"}
  merged -->|"否"| keep
  merged -->|"是"| remove["删除 worktree"]

有未提交改动的 worktree,或者其分支上还有尚未进入你主线的工作,都会原样保留。删掉的文件夹可以重建,丢掉的工作却回不来。对分支也一样谨慎:应用会记录自己创建的分支,并且只动这些分支。

这对你意味着什么

每个 worker 都有自己的分支之后,"同时跑四个智能体"就不再是一场赌博。你可以:

  • 给 manager 一条能拆成独立任务的指令,让 worker 们并行工作;
  • 单独阅读任何一个 worker 的 diff,旁边就是产生它的对话;
  • 拒绝某个 worker 的改动,而不影响其他人;
  • 团队工作时,你自己照常使用主检出。

这和人类团队遵守的纪律是一样的,只是用在了那些不会提醒你"我们快踩到对方脚了"的智能体身上。如果你好奇我们为什么要围绕这件事做一整个应用,第一篇文章讲了这个故事。

试一试

14 天试用为 Premium,无需绑卡。下载 SuperDevSpace,把一个新组织指向某个仓库,看着 manager 招聘第一批 worker 时一个个 worktree 随之出现。

SuperDevSpace

由打造 SuperDevSpace 的团队撰写。SuperDevSpace 是一款桌面应用,让一支 AI 编程智能体团队运行在你已有的 CLI 订阅上。

分享

接收发布通知邮件

SuperDevSpace 向所有人开放时,我们只发一封邮件。你需要先在收件箱中确认地址,退订只需一次点击。

拥有你自己的 AI 团队

SuperDevSpace 使用你已有的 CLI 订阅运行。14 天免费试用,无需绑卡。

免费试用

继续阅读