tech官小西

Git Worktree:AI 编程 Agent 的轻量级任务隔离方案

AI 编程 Agent —— Claude Code、Cursor 的 Agent 模式、OpenAI Codex CLI、Copilot —— 越来越自主。它们阅读你的代码库,规划修改,编辑文件,有时也会犯错。默认工作流"让 Agent 直接在主工作目录里操作"带来了一个严重问题:Agent 做到一半的代码、实验性分支和失败尝试全都污染了你的工作区。

Git worktree 优雅地解决了这个问题。它让每个 Agent(或每个任务)拥有独立的工作目录 —— 同一个仓库、同一个 .git 目录、完全独立的文件系统状态。无需 clone,无需 stash,无需来回 git checkout

Git Worktree 到底是什么

一个 git worktree 是挂载到同一个仓库的额外工作目录。不同于 git clone 给你的那个"唯一"工作树,你可以有多个 —— 每个检出到不同分支或 commit,每个有自己的 HEAD、暂存区和已修改文件。

# 主仓库
~/workspace/project/          # 检出到 main

# 创建一个关联 worktree 用于开发特性
git worktree add ../project-feature feature-branch

# 创建一个临时 worktree,挂载到特定 commit
git worktree add -d ../project-review abc1234

核心设计:所有 worktree 共享同一个 .git 目录(对象数据库)。commits、blobs、refs 对所有人可见。但每个 worktree 有自己的 HEAD、索引(暂存区)和磁盘文件 —— 完全相互隔离。

这意味着:

  • 可以在一个 worktree 里 npm install,不影响其他 worktree
  • 可以在 Agent 的 worktree 里 rm -rf,主工作区毫发无损
  • 可以在树 A 里 git checkout feature-a,同时在树 B 里 git checkout hotfix
  • 任何 worktree 里的 git commit 立即对所有 worktree 可见

为什么这对 AI Agent 至关重要

问题 1:被污染的工作区

你正在 main 上工作,但让 Agent 去实现一个新特性。Agent 创建文件、修改已有代码、运行 npm install、可能还加了测试 fixture。现在你的编辑器显示 37 个变更文件,其中 12 个你根本没想动。你没法跑自己的测试因为 Agent 搞坏了什么东西。你没法切分支因为有未提交的修改。

用 worktree 后:

# Agent 获得自己的沙箱
git worktree add ../project-agent-task feature/new-auth

# Agent 在 ../project-agent-task/ 里工作
# 你的主工作区 ~/workspace/project/ 完全不被打扰

当 Agent 完工且你审查通过后,从主树 merge。如果 Agent 的工作是垃圾,git worktree remove ../project-agent-task,瞬间消失。

问题 2:并行 Agent 任务

想同时运行两个 Agent —— 一个实现认证系统,另一个做性能优化?没有 worktree,它们会争夺同一套文件。有了 worktree:

git worktree add ../project-auth feature/auth
git worktree add ../project-perf feature/perf

# Agent A 在 ../project-auth/ 里工作
# Agent B 在 ../project-perf/ 里工作
# 它们永远碰不到对方的文件

两个 Agent 共享同一个对象数据库,所以一个 commit 后,另一个能立刻看到那个 commit。直到你选择 merge 之前,不会发生合并冲突。

问题 3:无中断的代码审查

当 AI Agent 提交了一个 PR,你需要审查。但检查 PR 分支意味着 stash 当前工作、切换分支、重新构建、审查 —— 然后再切回来。用 worktree:

# 创建一个审查 worktree,保持你的工作不动
git worktree add ../project-review feature/agent-pr

# 在 ../project-review/ 里审查
# 主工作区仍然停留在你正在做的事情上

问题 4:零代价实验

AI Agent 擅长生成实验性代码 —— "试试用 Rust 而不是 Python 实现这个"、"看看换成这个库能不能减小打包体积"。这些实验经常失败。用 worktree,失败零清理成本:

# Agent 在一次性 worktree 里实验
git worktree add -d ../project-experiment main

# Agent 工作,实验失败,直接删掉
git worktree remove ../project-experiment

# 或者:Agent 成功,cherry-pick 好的 commits
git cherry-pick <commit-hash>

AI Agent 工作流模式

以下是我在 Hermes Agent 和 Claude Code 中实际使用的模式:

单 Agent,单任务

# 1. 从 main 创建隔离工作区
git worktree add /tmp/agent-workspace feature/task-name

# 2. 复制 Agent 需要的非 git 上下文
cp .env.example /tmp/agent-workspace/.env

# 3. 让 Agent 指向 worktree
cd /tmp/agent-workspace
# Agent 运行,提交更改

# 4. 从主工作区审查
cd ~/workspace/project
git log feature/task-name  # 看 Agent 做了什么
git diff main..feature/task-name  # 审查所有变更

# 5. 满意就合并
git merge feature/task-name

# 6. 清理
git worktree remove /tmp/agent-workspace

多 Agent,并行任务

# 并行启动三个 Agent
for task in auth api-docs testing; do
  git worktree add ../agent-$task feature/$task
  # 在 ../agent-$task/ 中启动 Agent 进程(后台)
done

# 等所有完成,然后审查
for task in auth api-docs testing; do
  git diff main..feature/$task
done

Worktree vs. 其他隔离策略

策略 创建时间 磁盘占用 隔离级别 合并复杂度
git worktree 瞬时 ~0(共享 .git) 文件系统级 同仓库,简单
git clone 几分钟 完整副本 完全隔离 跨仓库,麻烦
Docker volume 几分钟 容器开销 进程级 在 git 之外
git stash + 切分支 几秒 ~0 无隔离 手动操作,易出错
原地切分支 几秒 ~0 无隔离 工作区混乱

结论很明确:worktree 提供了 clone 级别的隔离,但有本地分支切换的速度,且没有合并摩擦。

Worktree 的内部原理

当你运行 git worktree add 时,git 创建:

  1. 一个目录 —— 磁盘上指定路径的新工作树
  2. 一个 .git 文件 —— 不是目录,而是一个纯文本文件,内容是 gitdir: /path/to/main/.git/worktrees/<name>
  3. 元数据 —— $GIT_DIR/worktrees/<name>/ 包含 HEADindexORIG_HEAD 和其他 per-worktree 状态

.git 文件是魔法所在。这就是为什么 git statusgit loggit commit 都正常工作 —— git 沿着指针回到主对象数据库,同时使用 worktree 自己的 HEAD 和 index。

这个架构有两个重要属性:

  • 所有 worktree 共享 commits、blobs、trees —— 一个 worktree 里做的 commit,在其他 worktree 里 git log 立即可见
  • 跨 worktree 的 git 操作是安全的 —— 你不能在两个 worktree 里同时检出同一个分支(git 会阻止),防止了"哪个才是真正版本?"的问题

需要注意的限制

  • 同一个分支只能在一个 worktree 中被检出 —— 这是安全特性,不是 bug
  • 子模块是 per-worktree 的 —— 每个 worktree 有自己独立的子模块检出(git 2.34+ 正确处理)
  • git worktree remove 拒绝脏 worktree —— 确定要删除时用 -f 强制
  • 网络共享盘需要锁定 —— 如果 worktree 在可移动设备上,用 git worktree lock 防止被 prune
  • IDE 支持各不相同 —— VS Code 处理 worktree 很好(直接打开文件夹);JetBrains IDE 有时需要把 worktree 注册为单独项目

实用建议

  1. 用任务名而非分支名命名 worktree —— ../agent-add-oauth../feature/oauth 更直观,尤其是在开着 5 个终端的时候
  2. 在 Linux 上用 /tmp 存放一次性 worktree —— 系统重启自动清理
  3. 重度使用 worktree 时设置 gc.worktreePruneExpire = never —— 默认的 3 个月过期时间可能会删除你还在用的 worktree 元数据
  4. 考虑统一的 worktree 目录约定 —— ~/w/project/{main,task-1,task-2} 保持一切井井有条
  5. worktree 之间共享 node_modules 的技巧 —— 如果需要,可以用符号链接 ln -s ../main/node_modules .,但注意版本一致性

更大的图景

AI Agent 正在成为代码生成、修改和审查的主要界面。当一个开发者和 3 个 Agent 同时试图修改同一个目录时,那个为我们服务了几十年的"一人一工作区"模型就崩溃了。

Git worktree 是修复这个问题的轻量级抽象层。它从 git 2.5(2015 年)就存在了,久经考验,零成本上手,在不引入新工具或工作流的前提下解决了隔离问题。

下次你委托任务给 AI Agent 时,给它一个 worktree。你的主工作区会感激你。