1. 引言:那个让你抓狂的“突发需求”
想象一下这个场景:
你正在 feature-awesome 分支上热火朝天地写着几百行核心代码,正处于“心流”状态。突然,老板冲进办公室:“生产环境出 Bug 了,赶紧切到 master 修复一下!”
此时的你陷入了纠结:
- 方案 A:
git stash。把改了一半的代码藏起来。等你修完 Bug 回来stash pop时,往往会因为忘记了当时的环境或者遇到冲突而一脸懵。 - 方案 B:直接
git checkout。报错!Git 提醒你本地修改会被覆盖,切不过去。 - 方案 C:暴力
git clone。在另一个文件夹再克隆一份项目。不仅浪费硬盘空间,还得重新装依赖、配置环境变量,半小时过去了。
有没有一种办法,能让我像切浏览器标签页一样,同时打开多个分支工作,互不干扰?
这就是我们要聊的主角:Git Worktree。
2. 什么是 Git Worktree?
Git Worktree 是 Git 的一个高级功能,允许你基于同一个本地 Git 仓库,在不同的文件夹里同时检出(checkout)多个不同的分支。
传统方式的痛点
通常你在一个文件夹里只能处于一个分支。如果你想同时看两个分支的代码,你要么频繁地 git checkout 切来切去,要么把整个仓库重新 git clone 一份(浪费硬盘空间且不同步)。
Worktree 的优势
- 秒级创建:不需要重新下载或复制(
.git目录里的历史数据是共享的) - 完全隔离:每个 worktree 都有自己独立的运行环境、
node_modules等,互不干扰 - 状态同步:因为底层是同一个仓库,在一个工作区提交的代码,在另一个工作区切换分支立刻就能看到
3. 通俗比喻
比喻一:共享云盘
把 Git 仓库想象成一个带密码的共享云盘。
- 传统的 Git:你本地只有一个文件夹(本地副本)。你想看另一个分支的代码,就必须把当前的文件夹内容替换掉。
- Git Worktree:你在本地同时打开了两个独立的文件夹窗口。这两个窗口都能看到云盘里的所有内容(所有分支),但你可以在窗口 A 里切换到分支 A,在窗口 B 里切换到分支 B。它们操作的是同一个云盘,提交的文件会自动同步到云端。
比喻二:书本的全息投影
假设你的项目是一本厚厚的书,项目的 .git 隐藏文件夹就是这本书的**“核心记忆库”**。
- 传统的 Git:你桌子上只有一个阅读架(一个目录)。想看 A 分支的代码就摆 A,想看 B 分支就必须把 A 收起来换成 B。无法同时摊开对比。
- 传统的笨办法(Copy 一份整个项目):相当于去书店又买了一本一模一样的书。缺点是极度浪费硬盘空间,且两本书是断开连接的。
- Git Worktree(魔法分身):召唤出这本书的**“全息投影”。你可以同时在两个文件夹里看不同分支的内容,但它们共享同一个“核心记忆库”**。
比喻三:乐高工作台
想象你正在拼一套复杂的“星球大战”乐高(这是你的主项目)。
- 传统的 Git 像是一个只有一个桌面的工作台。你想拼“死星”,就得把还没拼好的“千年隼”拆掉或收进盒子里,腾出地方。
- Git Worktree 则是给你瞬间变出第二个、第三个独立的工作台。这些工作台共享同一个零件仓库(
.git目录),但桌面是独立的。你可以在台子 A 修 Bug,在台子 B 写新功能,抬头就能看见彼此,转身就能切换。
4. 使用场景
Git Worktree 适用于以下场景:
场景一:紧急 Bug 修复 + 功能开发并行
当你正在开发新功能时,突然需要去修复生产环境的 Bug。使用 Worktree,你可以:
- 在主目录继续开发新功能(不中断工作流)
- 创建一个新的 Worktree 去修复 Bug
- Bug 修复完成后,合并代码,回到主目录继续写代码
场景二:多任务并行(双 AI 竞技)
你想让两个 AI 各自实现同一个功能,然后比较效果。
- 为 AI-A 创建一个 Worktree + 新分支
- 为 AI-B 创建一个 Worktree + 新分支
- 两个 AI 同时在各自的目录里写代码
- 完成后对比效果,选择更好的合并
场景三:代码审查
在提交 PR 之前,想在本地先跑一下另一个分支的代码看看效果?
- 创建一个 Worktree 检出那个分支
- 审查完毕后删除 Worktree
场景四:并行测试
需要在同一个项目上跑不同的测试套件,但测试会修改代码?
- 创建多个 Worktree,每个跑不同的测试
- 互不干扰
5. 底层原理:.git 文件夹的变化
核心逻辑
在 Git 的世界里,一个仓库通常由两部分组成:
.git文件夹(仓库的灵魂:存储历史、版本信息)- 工作区(仓库的肉体:你实际看到的代码文件)
默认情况下,一个灵魂只配一个肉体。但 Git Worktree 允许一个 .git 文件夹同时管理多个工作区。
主目录(Main Worktree)
假设你的主项目在 D:\projectA,里面有一个真正的 .git 文件夹,包含了项目所有的历史提交记录、代码对象库等。
使用 worktree 后,Git 会在 D:\projectA\.git\ 里面悄悄新建一个 worktrees 子文件夹:
D:\projectA\
├── .git/ <-- 真正的文件夹
│ ├── objects/ <-- 存放所有历史代码(体积最大,两边共享)
│ ├── config <-- 共享的配置文件
│ └── worktrees/ <-- 新增的秘密基地
│ └── projectB/ <-- 记录 projectB 状态的子文件夹
│ ├── HEAD <-- 记录 projectB 当前停留在哪个分支
│ └── index <-- 记录 projectB 的暂存区
└── package.json ...
新工作区(Linked Worktree)
新创建的 worktree 目录里,.git 不是一个文件夹,而是一个普通的文本文件,里面只有一行字:
gitdir: D:/projectA/.git/worktrees/projectB
这就是为什么新目录几乎不占空间 —— 它只是一个“指针”,指向主项目的数据库。
6. 核心概念:分支关系
⚠️ 重要提醒:工作区应建在主项目的同级目录
不要把 worktree 目录建在主项目文件夹里面!
正确做法:使用 ../ 路径,建在主项目的上一级目录(即同级目录)。
# 假设主项目在 D:\projects\my-app
# 正确:建在 D:\projects\my-app-ai-a
git worktree add ../my-project-ai-a -b ai-a-task
# 错误:会污染主项目目录!
# git worktree add ./my-app-ai-a -b ai-a-task ❌
这样创建后,文件系统是这样的:
D:\projects\
├── my-app/ <-- 你的主项目(干净)
├── my-app-ai-a/ <-- AI-A 的工作区(独立)
└── my-app-ai-b/ <-- AI-B 的工作区(独立)
合并代码后,用 git worktree remove 清理,主项目目录依然是干净的。
分支是全局共享的
多个 worktree 之间,分支列表是完全共享的。
- 如果你在 AI-A 的 worktree 目录里新建了一个分支
git branch test-ai - 你马上切回到主目录,敲
git branch,会立刻看到test-ai这个分支 - 它们共享同一个大本营
代码提交是瞬间同步的
因为底层数据库是同一个:
- AI-A 在它的目录里,在
ai-a-task分支上做了一个 Commit - 这个 Commit 瞬间被永久写入主目录的
.git数据库里 - 哪怕你把 AI-A 的实体文件夹物理删除了,代码也不会丢
Worktree 分支与原项目分支的关系
它们根本就是同一个东西。没有任何区别,完全共享。
⚠️ 关键点(必读):在 Worktree 目录里的所有操作(提交、推送),都是直接作用于对应的分支。
git worktree add ../my-project-hotfix hotfix创建的工作区,检出的就是hotfix分支- 在这个目录里
git commit,代码直接提交到本地的hotfix分支- 在这个目录里
git push,代码直接推送到远端的hotfix分支- 不存在"属于哪个项目"的区别,这个 Worktree 就是分支的"另一个窗口"
不要把 worktree 想象成"主仓库的克隆/子仓库"。你可以把整个 Git 仓库想象成一个**"共享保险箱(.git 目录)"**,里面存放着所有的代码和所有的分支。
- 在 Worktree B 里的提交 = 直接修改主项目的分支 A
- 不存在"主项目的 A 分支"和"B 项目的 A 分支"这种区分
- 在 worktree 目录 B 中对分支 A 做提交:
- Commit 的数据写入主项目的
.git/objects数据库 - 分支 A 的指针向前移动
- 回到主项目执行
git log A能立刻看到这个提交
- Commit 的数据写入主项目的
最重要规则:互斥检出
同一个分支,同一时刻,只能被一个目录使用。
- 假设主目录当前停留在
main分支 - 如果此时你敲
git worktree add ../new-dir main,Git 会直接报错拒绝 - Git 的理由是:主目录正在使用
main分支,新目录必须用别的分支,防止同时改文件导致混乱
7. 双 AI 竞技实战流程
步骤一:创建 Worktree
在主项目目录下执行:
# 为 AI-A 创建一个新分支 ai-a-task,并放到 ../my-project-ai-a 文件夹
git worktree add ../my-project-ai-a -b ai-a-task
# 为 AI-B 创建一个新分支 ai-b-task,并放到 ../my-project-ai-b 文件夹
git worktree add ../my-project-ai-b -b ai-b-task
注意:路径 ../ 表示建在主项目的上一级目录,避免污染主项目。
步骤二:让 AI 开始干活
- 让 AI-A 在
my-project-ai-a文件夹里写代码 - 让 AI-B 在
my-project-ai-b文件夹里写代码 - 它们可以同时运行自己的开发服务器、独立安装依赖,完全不会冲突
步骤三:比较效果
- 分别在两个目录下运行项目,直观对比 UI 或功能效果
- 或者使用
git diff ai-a-task..ai-b-task比对代码差异
步骤四:合并代码(假设 AI-A 写得更好)
- 回到主项目目录
- 合并 AI-A 的分支
cd ../my-project
git checkout dev # 确保你在开发分支
git merge ai-a-task # 把 AI-A 的劳动成果合并过来
步骤五:清理 Worktree
代码已经合并了,临时目录使命结束:
# 删除 worktree 目录(Git 会自动从硬盘删除这两个文件夹)
git worktree remove ../my-project-ai-a
git worktree remove ../my-project-ai-b
# 可选:删除临时分支
git branch -d ai-a-task
git branch -d ai-b-task
8. 命令详解
创建 Worktree
# 方式一:创建一个全新的分支(推荐用于新任务)
git worktree add <路径> -b <新分支名>
# 方式二:基于已存在的分支(本地或远端)
git worktree add <路径> <分支名>
示例 1:本地没有该分支,Git 会自动从远端拉取
git worktree add ../my-project-hotfix hotfix
- 如果本地没有
hotfix分支,Git 会自动去远端找 - 自动在本地创建
hotfix分支,与远端关联 - 然后检出到新目录
示例 2:创建全新的分支
git worktree add ../my-project-ai-a -b ai-a-task
-b表示创建并切换到一个全新的分支- 适合让 AI 开始干一个全新的任务
查看 Worktree 列表
git worktree list
移除 Worktree
# 安全删除(确保没有未提交的代码)
git worktree remove <路径>
# 强制删除(如果有未提交的代码)
git worktree remove <路径> --force
清理无效 Worktree
如果手动删除了 worktree 文件夹,但没告诉 Git:
git worktree prune
9. 常见问题
Q: Worktree 里的提交属于主项目的分支吗?
是的,完全属于。
⚠️ 再次强调:在 Worktree 目录里的提交和推送,都是直接作用于对应的分支。
例如:你执行了
git worktree add ../my-project-hotfix hotfix,然后在my-project-hotfix目录里:cd ../my-project-hotfix echo "fix bug" > bug.txt git add . git commit -m "修复了一个Bug" git push origin hotfix # 推送到远端的 hotfix 分支
- 这个 Commit 直接写入
hotfix分支的历史- 回到主项目执行
git log hotfix能立刻看到这个提交- 推送到远端时,推送的是
hotfix分支,不是新建了一个分支- 在 Worktree 里提交 = 直接修改分支,推送 = 直接推送到该分支的远端
在 Git Worktree 的世界里,根本不存在"主项目的 A 分支"和"B 项目的 A 分支"这种区分。整个仓库里,自始至终只有一个 A 分支。
在 worktree 目录 B 中对分支 A 做提交:
- Commit 的数据写入主项目的
.git/objects数据库 - 分支 A 的指针向前移动
- 回到主项目执行
git log A能立刻看到这个提交
Q: 本地没有某个分支,但远端有,怎么创建 Worktree?
直接写分支名即可,不需要写 origin/xxx:
git worktree add ../new-dir hotfix
Git 会自动检测本地没有这个分支,然后去远端拉取并创建本地分支。
注意:不要写成 git worktree add ../new-dir origin/hotfix,这会导致你在新目录里处于“游离状态(Detached HEAD)”,无法正常提交。
Q: 两个 worktree 可以同时使用同一个分支吗?
不能。Git 会报错:
fatal: 'main' is already checked out at '.../主项目目录'
这是为了防止两个目录同时修改同一个分支导致冲突。
Q: Worktree 目录可以建在主项目里面吗?
不推荐。虽然技术上可以,但会污染主项目的目录结构。
推荐做法:始终使用 ../ 路径,建在主项目的同级目录。这样:
- 主项目目录保持干净
- 合并代码后,用
git worktree remove清理,物理文件夹会自动消失 - 不会把 worktree 的文件误提交到主项目
10. 完整工作流示例
# 1. 在主项目目录(假设在 D:\projects\my-app),创建两个 worktree
git worktree add ../my-app-ai-a -b ai-a-task
git worktree add ../my-app-ai-b -b ai-b-task
# 2. AI-A 和 AI-B 分别在各自的目录里写代码、提交
# (假设 AI-A 完成了)
# 3. 回到主项目,合并 AI-A 的代码
cd ../my-app
git checkout dev
git merge ai-a-task
# 4. 清理:删除 worktree 和临时分支
git worktree remove ../my-app-ai-a
git worktree remove ../my-app-ai-b
git branch -d ai-a-task
git branch -d ai-b-task
# 5. 完成后,主目录依然是干净的,只有 my-app 一个文件夹
11. Cursor Worktree vs Git Worktree
本节介绍 Cursor 编辑器的 Worktree 功能,它是 Git 原生 Worktree 的“AI 增强版”。
什么是 Cursor Worktree?
Cursor 的 Worktree 是建立在 Git 原生 Worktree 之上的“AI 增强版工作区”。
Cursor 利用 Git Worktree 的底层能力,但在此基础上添加了自动化管理、智能对比和一键合并等功能,专门为"让多个 AI 代理同时干活"这个场景优化。
核心区别
| 特性 | Git 原生 Worktree | Cursor Worktree |
|---|---|---|
| 创建方式 | 手动敲命令 git worktree add | AI 自动创建,你只需要点按钮 |
| 分支管理 | 手动创建、切换、删除 | 自动为每个 Agent 创建独立分支 |
| 代码合并 | 手动 git merge | 点击"Apply"按钮一键合并 |
| 多模型对比 | 需自己搭建 | 内置"Best-of-N"功能,多个模型同时跑,结果对比展示 |
| 初始化 | 无自带机制 | 支持 worktrees.json 自动安装依赖、复制环境变量 |
| 清理机制 | 手动 git worktree remove | 自动清理(最多20个,按访问时间删除) |
它们之间的联系
Cursor Worktree 就是 Git 原生 Worktree 的“高级封装”。
当你用 Cursor 创建一个并行代理时:
- Cursor 会在后台调用
git worktree add创建新目录 - 分支是自动创建的(比如
feat-1-98Zlw) - 文件路径类似
/Users/<you>/.cursor/worktrees/<repo>/98Zlw
从终端运行 git worktree list,你会看到:
/.../<repo> 15ae12e [main]
/Users/<you>/.cursor/worktrees/<repo>/98Zlw 15ae12e [feat-1-98Zlw]
/Users/<you>/.cursor/worktrees/<repo>/a4Xiu 15ae12e [feat-2-a4Xiu]
本质上就是 Git Worktree,只是 Cursor 帮你做了:
- 自动创建
- 自动清理
- 自动复制环境变量
- 可视化的合并界面
Cursor Worktree 的独特优势
1. Best-of-N(多模型竞技)
这是 Cursor 独有的功能:
- 同一个提示词,让多个模型同时跑
- 生成多张卡片,分别展示每个模型的改动
- 你可以对比挑选最好的结果,一键 Apply
2. 初始化脚本(开箱即用)
通过 .cursor/worktrees.json 配置,新 Worktree 创建时自动:
- 安装依赖(
npm ci/pnpm install) - 复制环境变量文件(
.env) - 运行数据库迁移
3. 自动清理防占盘
- 最多 20 个 Worktree
- 自动删除最早访问的
- 不需要手动管理
总结:一句话理解
Cursor Worktree 就是“Git Worktree 的懒人版”,它把创建分支、装依赖、合并代码这些脏活累活都替你干了,你只需要点按钮让 AI 干活,然后挑最好的结果合并进来。
12. 总结
11. 总结
- Worktree 不是克隆仓库,而是给同一个仓库开了多个“操作窗口”
- 分支是共享的,不是独立的副本
- 代码提交在哪里提交,就属于哪个分支,不存在“属于哪个项目”的区别
- 用完即焚,通过
git worktree remove清理 - 工作区应建在主项目的同级目录,避免污染主项目
- 它比
stash更安全,比clone更轻量(共享.git目录,极省空间)