# Git Worktree 简明指南
> `git worktree` 的核心作用:**一个 Git 仓库,同时开出多个独立工作目录**。每个目录可以停在不同分支,互不打断,适合并行开发、紧急修 bug、PR review、跑多个 agent。
---
## Level 1 · 它到底解决什么问题
普通 Git 工作流里,一个仓库目录一次只能检出一个分支:
```bash
cd my-project
git switch main
# 或
git switch feature/payment
```
如果你正在 `feature/payment` 上改到一半,突然要修线上 bug,就会遇到三件麻烦事:
1. 当前改动还没提交
2. 不能直接切分支
3. 只能先 `stash`,修完再 `stash pop`
典型流程会变成:
```bash
git stash
git switch main
git switch -c fix/login-bug
# 修 bug
git switch feature/payment
git stash pop
```
这不是不能用,但会严重打断思路。
`git worktree` 的思路是:**不要在同一个目录里反复切分支,而是给每个任务一个目录。**
例如:
```text
~/code/my-project/ # main
~/code/my-project-feature-payment/ # feature/payment
~/code/my-project-fix-login/ # fix/login-bug
```
它们共享同一个 Git 仓库历史,但工作目录彼此独立。
---
## Level 2 · 先看有哪些 worktree
在任意一个 worktree 里执行:
```bash
git worktree list
```
示例:
```text
/home/me/code/my-project abc1234 [main]
/home/me/code/my-project-feature-payment def5678 [feature/payment]
/home/me/code/my-project-fix-login 9988776 [fix/login-bug]
```
每一行大概是:
```text
路径 当前 commit 当前分支
```
这条命令很重要。只要你忘了自己开过哪些目录,先执行它。
---
## Level 3 · 基于已有分支创建 worktree
如果远程或本地已经有一个分支:
```bash
feature/payment
```
可以创建一个对应的工作目录:
```bash
git worktree add ../my-project-feature-payment feature/payment
```
格式是:
```bash
git worktree add <新目录路径> <分支名>
```
然后进入新目录:
```bash
cd ../my-project-feature-payment
git branch --show-current
```
输出应该是:
```text
feature/payment
```
从这里开始,你就像在普通仓库里一样开发、提交、推送。
---
## Level 4 · 创建 worktree 的同时新建分支
更常见的场景是:从 `main` 开一个新分支,并放进新 worktree。
```bash
git worktree add -b fix/login-bug ../my-project-fix-login main
```
格式是:
```bash
git worktree add -b <新分支名> <新目录路径> <基于哪个分支>
```
这条命令等价于三件事:
1. 从 `main` 创建 `fix/login-bug`
2. 创建目录 `../my-project-fix-login`
3. 把 `fix/login-bug` 检出到这个目录
进入新目录:
```bash
cd ../my-project-fix-login
```
确认分支:
```bash
git branch --show-current
```
---
## Level 5 · 一个完整日常流程
假设主仓库在:
```bash
~/code/my-project
```
你要修一个登录 bug。
### 1. 主目录保持在 main
```bash
cd ~/code/my-project
git switch main
git pull
```
### 2. 创建 bugfix worktree
```bash
git worktree add -b fix/login-error ../my-project-fix-login-error main
```
### 3. 进入新目录开发
```bash
cd ../my-project-fix-login-error
```
修改代码,跑测试,然后提交:
```bash
git status
git add .
git commit -m "fix: handle login error correctly"
```
### 4. 推送分支
```bash
git push -u origin fix/login-error
```
然后正常创建 PR。
### 5. PR 合并后清理
先回到别的目录,不要站在要删除的 worktree 里面删自己:
```bash
cd ~/code/my-project
```
删除 worktree:
```bash
git worktree remove ../my-project-fix-login-error
```
删除本地分支:
```bash
git branch -d fix/login-error
```
如果远程分支也要删:
```bash
git push origin --delete fix/login-error
```
---
## Level 6 · 推荐目录结构
推荐把 worktree 放在主仓库同级目录,而不是主仓库内部。
推荐:
```text
~/code/
my-project/ # main
my-project-feature-payment/ # feature/payment
my-project-fix-login/ # fix/login-bug
my-project-review-123/ # review PR #123
```
不太推荐:
```text
~/code/my-project/
worktrees/
fix-login/
```
原因很简单:放在仓库内部,编辑器、搜索、构建工具、测试工具可能会把里面的文件也扫进去,容易混乱。
目录名最好带上任务含义:
```bash
my-project-fix-login
my-project-feature-payment
my-project-refactor-auth
my-project-review-pr-123
```
不要叫:
```bash
test
new
tmp
copy
```
几天后你会完全忘记它们是什么。
---
## Level 7 · 删除和清理
正常删除:
```bash
git worktree remove ../my-project-feature-payment
```
如果目录里还有未提交改动,Git 会阻止删除。
先检查:
```bash
cd ../my-project-feature-payment
git status
```
确认真的不要了,再强制删除:
```bash
git worktree remove --force ../my-project-feature-payment
```
如果你曾经手动删过目录:
```bash
rm -rf ../my-project-old-task
```
Git 可能还留着一条过期记录。清理它:
```bash
git worktree prune
```
再看列表:
```bash
git worktree list
```
---
## Level 8 · 常见坑
### 1. 同一个分支不能同时被两个 worktree 使用
如果 `main` 已经在主目录里被检出:
```text
~/code/my-project [main]
```
再执行:
```bash
git worktree add ../my-project-main-copy main
```
可能会报错:
```text
fatal: 'main' is already checked out
```
这是正常限制:同一个分支默认不能同时在两个 worktree 里检出。
如果只是想临时看一下 `main` 的内容,可以用 detached 模式:
```bash
git worktree add --detach ../my-project-main-copy main
```
但日常开发不要长期在 detached 状态下工作,容易忘记提交落在哪个分支上。
### 2. 不要直接 `rm -rf` 删除 worktree
优先用:
```bash
git worktree remove <path>
```
它会同时清理 Git 内部记录。
如果已经手动删了,再补:
```bash
git worktree prune
```
### 3. 先确认当前目录和分支
worktree 多了以后,最容易搞错的是:人以为自己在 A 任务,实际终端停在 B 目录。
动手前养成习惯:
```bash
pwd
git branch --show-current
git status
```
---
## Level 9 · 和 clone、stash 的区别
### worktree vs clone
你也可以重新 clone 一份仓库:
```bash
git clone git@github.com:xxx/my-project.git my-project-copy
```
但 clone 是完整复制一份仓库。
`worktree` 是在同一个仓库对象库上开多个工作目录,更轻量,也更适合本机并行分支开发。
| 方式 | 特点 |
|---|---|
| `git clone` | 完整复制一份仓库,彼此更独立 |
| `git worktree` | 共享同一份 Git 历史,只增加工作目录 |
### worktree vs stash
| 场景 | 更适合 |
|---|---|
| 临时切一下分支,改动很少 | `git stash` |
| 同时长期处理多个任务 | `git worktree` |
| 紧急 bugfix,不想打断当前开发 | `git worktree` |
| 同时跑两个分支的项目 | `git worktree` |
| 多个 agent 并行改同一个仓库 | `git worktree` |
一句话:
> `stash` 是把当前改动临时收起来;`worktree` 是给另一个任务直接开一张新桌子。
---
## Level 10 · Agent 场景下为什么常见
很多 coding agent 会用 worktree 做隔离。
根本原因是:如果两个 agent 同时在同一个目录里改文件,它们会互相冲突。一个 agent 改到一半,另一个 agent 也改同一个文件,工作区很快就乱了。
用 worktree 后,可以变成:
```text
repo-agent-task-a/ # agent A 的分支
repo-agent-task-b/ # agent B 的分支
repo-agent-review/ # review 分支
```
它们共享历史,但文件系统层面互不干扰。每个 agent 在自己的目录里工作,最后通过 Git merge / rebase / PR 来合并结果。
所以在多 agent、后台任务、自动修 CI、并行实验这些场景里,worktree 是很自然的基础设施。
---
## 常用命令速查
查看所有 worktree:
```bash
git worktree list
```
基于已有分支创建 worktree:
```bash
git worktree add ../my-project-feature feature/payment
```
创建 worktree 的同时新建分支:
```bash
git worktree add -b feature/payment ../my-project-feature-payment main
```
删除 worktree:
```bash
git worktree remove ../my-project-feature-payment
```
强制删除:
```bash
git worktree remove --force ../my-project-feature-payment
```
清理过期记录:
```bash
git worktree prune
```
查看当前分支:
```bash
git branch --show-current
```
---
## 最小心智模型
记住三句话就够了:
1. `git worktree` 让一个仓库同时拥有多个工作目录。
2. 每个 worktree 通常对应一个分支,适合一个任务一个目录。
3. 创建用 `git worktree add`,结束用 `git worktree remove`,别直接 `rm -rf`。
最常用的命令是:
```bash
git worktree add -b <branch> <path> <base>
git worktree list
git worktree remove <path>
```
如果你经常在多个分支之间来回切,或者需要并行处理多个任务,worktree 通常比反复 `checkout` + `stash` 更清楚。