在日常开发中,我们经常遇到这种场景:正在开发一个功能,突然要去改另一个分支的紧急 bug,于是不得不 git stash 或 git commit -m "wip",切分支、改完、切回来、再恢复现场。分支一多,切换成本和心智负担指数级上升。
git worktree 提供了另一种思路:让同一个仓库同时存在多个工作目录,每个目录绑定不同分支,彼此物理隔离,但共享同一份 git 历史。
本文结合一个实际演示走完全流程。
一、它解决什么问题
- 频繁切分支的成本:不用再 stash/临时提交,每个分支拥有自己独立的工作目录。
- 并行开发多个功能:多个 IDE 窗口、多个终端、甚至多个 AI Agent(Claude Code / Cursor)可以同时在不同功能上推进。
- 物理隔离:A 功能改动不会污染 B 功能目录下的文件。
- 失败成本低:某个分支被改烂,直接删目录重建 worktree,不动主仓库。
二、核心概念
一个 Git 仓库由两部分构成:
| 部分 | 作用 |
|---|---|
.git/ 目录 |
存储对象、引用、配置等全部历史数据 |
| 工作目录 | 检出的某个分支/提交的文件快照 |
传统用法里,一个仓库只有一个工作目录。Worktree 允许你给同一个 .git/ 挂多个工作目录,每个独立检出一个分支。
约束:同一分支只能被一个 worktree 检出。这其实是个好约束------避免两个地方同时改同一分支导致混乱。
三、实战:从零搭建
目标结构
bash
git WorkTree演示/
├── 主项目/ main 分支(基础项目)
├── feature-login/ feature/login 分支
├── feature-dashboard/ feature/dashboard 分支
└── feature-api/ feature/api 分支
1. 初始化基础项目
bash
cd "git WorkTree演示/主项目"
# 创建 index.js / README.md / .gitignore 等基础文件
git init -b main
git add .
git commit -m "chore: 初始化基础 JS 项目"
2. 创建功能分支
bash
git branch feature/login
git branch feature/dashboard
git branch feature/api
此时分支只是一组引用,并未检出。
3. 为每个分支添加 worktree
bash
git worktree add ../feature-login feature/login
git worktree add ../feature-dashboard feature/dashboard
git worktree add ../feature-api feature/api
执行完后,主项目/ 的同级会出现三个新目录,每个是一个完整可用的工作区。
4. 在各自 worktree 独立开发
例如在 feature-login/ 里添加登录逻辑:
bash
cd ../feature-login
# 创建 login.js
git add .
git commit -m "feat(login): 添加登录函数"
关键点:不需要 git checkout。进入目录就等于在对应分支上工作。
5. 验证物理隔离
bash
git worktree list
输出类似:
bash
.../主项目 b6e15a7 [main]
.../feature-api e8b3d5e [feature/api]
.../feature-dashboard a39343a [feature/dashboard]
.../feature-login 64fee00 [feature/login]
分别 ls 三个目录,你会看到:
主项目/只有基础文件feature-login/比基础多一个login.jsfeature-dashboard/比基础多一个dashboard.jsfeature-api/比基础多一个api.js
改动从不串台。
四、合并策略
合并在主 worktree(主项目/) 里执行,不需要也不能 checkout 被其他 worktree 占用的分支:
bash
cd 主项目/
git merge feature/login
git merge feature/dashboard
git merge feature/api
遇到冲突时:
- 在
主项目/解决冲突文件 git add <冲突文件>git commit完成合并
合并完成后,功能 worktree 可以选择删除(见下一节)。
五、常用命令速查
| 命令 | 作用 |
|---|---|
git worktree add <path> <branch> |
为已有分支创建 worktree |
git worktree add -b <new-branch> <path> |
新建分支并创建 worktree |
git worktree list |
列出所有 worktree |
git worktree remove <path> |
删除 worktree(目录 + 注册信息),分支仍保留 |
git worktree prune |
清理已被手动删除目录的残留注册 |
git worktree move <from> <to> |
移动 worktree 目录 |
git worktree lock <path> |
锁定,防止误删 |
六、Vibe Coding 场景下的价值
所谓 "vibe coding",指大量依赖 AI 生成代码、快速试错的工作流。Worktree 在这个场景下特别合拍:
- 并行多 Agent:同时开多个 Claude Code / Cursor 窗口,每个守一个 worktree,分别做不同功能,互不阻塞。
- 上下文干净:AI 读取当前目录文件时只会看到该功能相关的代码,减少噪音,生成质量更稳。
- 实验可抛弃 :让 AI 尝试一种激进方案时,新开 worktree + 新分支,失败就
git worktree remove+git branch -D,主仓库毫发无损。 - 对比方案:同一需求让 AI 在两个 worktree 各出一版,直接 diff 比较选优。
七、注意事项与踩坑
1. node_modules 不会自动共享
每个 worktree 都是独立工作目录,依赖目录需要各自安装或手动 symlink。对磁盘敏感或依赖庞大时,考虑 pnpm 的 content-addressable store,或用 ln -s 共享。
2. 跨模块的公共代码改动需要同步
如果三个 worktree 都依赖 shared/utils.js,而你在其中一个里修改了它,其他 worktree 需要主动 merge/rebase 拉取变更,否则会基于旧版本继续开发。
3. 一个分支只能被一个 worktree 检出
在主 worktree 里 git checkout feature/login 会报错。这是设计使然。如果你想在两个地方同时改同一分支------别这么做,冲突和数据丢失几乎必然。
4. 保持"我在哪个目录"的自觉
并行多 worktree 最大的心智负担是:当前终端究竟在哪个分支下?建议:
- 终端提示符加上当前分支(
PS1/ zsh theme) - 或每个 worktree 用不同 IDE 窗口 + 不同颜色主题区分
5. 删除流程
bash
git worktree remove ../feature-login # 推荐:连同目录和注册一起清理
git branch -d feature/login # 如果不再需要该分支
不要 rm -rf 目录后不管,会留下 stale 注册,需 git worktree prune 修复。
八、总结
Worktree 不是什么"高级特性",它是一种更契合现实开发节奏的仓库组织方式。它尤其适合:
- 功能独立、可并行推进的模块化开发
- AI 辅助的多方案试错流程
- 需要频繁在多个长期分支间切换的场景
反过来,如果你的工作流几乎总在同一个分支做小步提交,worktree 带来的收益不足以抵消多目录管理成本------这时传统的单目录 + 分支切换更顺手。
一句话:worktree 把"切换分支"从"时间上的串行"变成了"空间上的并行"。