Git 完全指南 / 12 - 工作树:worktree 管理、并行开发
第十二章:工作树(Worktree)
Worktree 让你在同一个仓库中同时检出多个分支,实现真正的并行开发。
12.1 工作树概述
git worktree 允许你将同一个仓库的多个分支同时检出到不同目录,无需 stash 或 commit 就能切换工作。
主工作树: /home/user/project/ → main 分支
├── .git/
├── src/
└── README.md
链接工作树: /home/user/project-feature/ → feature 分支
├── .git (指向主仓库)
├── src/
└── feature.js
链接工作树: /home/user/project-hotfix/ → hotfix 分支
├── .git (指向主仓库)
├── src/
└── hotfix.js
12.2 基本操作
12.2.1 创建工作树
# 基于当前分支创建新工作树
$ git worktree add ../project-feature feature-branch
# 基于指定提交创建新工作树
$ git worktree add ../project-fix abc1234
# 创建新分支并检出到工作树
$ git worktree add -b new-feature ../project-new-feature
# 基于远程分支创建
$ git worktree add -b hotfix ../project-hotfix origin/main
# 创建裸工作树(detached HEAD)
$ git worktree add --detach ../project-experiment HEAD~3
12.2.2 列出工作树
$ git worktree list
/home/user/project abc1234 [main]
/home/user/project-feature def5678 [feature]
/home/user/project-hotfix ghi9012 [hotfix]
# 详细信息
$ git worktree list --porcelain
12.2.3 移除工作树
# 移除工作树(保留分支)
$ git worktree remove ../project-feature
# 强制移除(即使有未提交的修改)
$ git worktree remove --force ../project-feature
# 手动清理后删除
$ rm -rf ../project-feature
$ git worktree prune
12.2.4 移动工作树
$ git worktree move ../project-feature ../project-feature-new
12.3 并行开发工作流
12.3.1 多分支同时开发
# 主仓库做日常开发
$ cd ~/project
# 同时处理热修复
$ git worktree add ../project-hotfix hotfix/critical-bug
$ cd ../project-hotfix
$ # 修复 bug...
# 同时开发新功能
$ git worktree add ../project-feature feature/new-api
$ cd ../project-feature
$ # 开发新功能...
# 三个目录,三个分支,互不干扰
12.3.2 代码审查场景
# 创建工作树来审查 PR
$ git worktree add ../pr-review origin/feature-branch
$ cd ../pr-review
$ npm test
$ npm run lint
$ cd ~/project
$ git worktree remove ../pr-review
12.3.3 运行多个版本
# 同时运行 v1 和 v2 进行对比
$ git worktree add ../project-v1 v1.0.0
$ git worktree add ../project-v2 v2.0.0
12.4 工作树内部原理
# 链接工作树中的 .git 是一个文件(不是目录)
$ cat ../project-feature/.git
gitdir: /home/user/project/.git/worktrees/project-feature
# 主仓库中的工作树元数据
$ ls .git/worktrees/project-feature/
HEAD 该工作树的 HEAD 指针
index 该工作树的暂存区
config 该工作树的本地配置
logs/ reflog 日志
refs/ 引用信息
# 每个工作树有独立的暂存区和配置
# 但共享 objects 目录(提交、tree、blob)
| 共享内容 | 独立内容 |
|---|---|
| objects(提交/文件内容) | HEAD 指针 |
| refs(远程引用) | 暂存区(index) |
| tags | 工作区文件 |
| hooks | 本地配置 |
12.5 工作树注意事项
# ⚠️ 注意 1:不能同时检出同一个分支
$ git worktree add ../project-main main
fatal: 'main' is already checked out at '/home/user/project'
# ⚠️ 注意 2:不能在链接工作树中创建子模块
# 需要在主工作树中操作
# ⚠️ 注意 3:有些操作需要在主工作树中执行
# - git worktree add/remove
# - git submodule 操作
# ⚠️ 注意 4:删除工作树前确保没有未提交的修改
$ git -C ../project-feature status
12.6 工作树最佳实践
# 1. 命名规范:../project-<分支名>
# 2. 完成后及时清理
$ git worktree list
$ git worktree remove ../project-feature
# 3. 清理无效的工作树引用
$ git worktree prune
# 4. 在 .gitignore 中添加工作树目录
echo "project-*/" >> .git/info/exclude
# 5. 定期检查工作树状态
$ git worktree list
/home/user/project abc1234 [main]
/home/user/project-feature def5678 [feature]
# 确认每个工作树都有对应的分支
# 6. 使用脚本自动化清理
# 清理已合并分支的工作树
$ for wt in $(git worktree list --porcelain | grep '^worktree' | sed 's/worktree //'); do
branch=$(git -C "$wt" symbolic-ref --short HEAD 2>/dev/null)
if [ -n "$branch" ] && git merge-base --is-ancestor "$branch" main; then
echo "Removing worktree for merged branch: $branch"
git worktree remove "$wt"
fi
done
12.5 工作树 vs 克隆
| 特性 | Worktree | Clone |
|---|---|---|
| 磁盘占用 | 共享 .git 目录,省空间 | 完整副本 |
| 切换速度 | 瞬间(无需 checkout) | 需要 clone |
| 分支同步 | 自动共享 | 需要 fetch/push |
| 适用场景 | 同一项目的多分支 | 独立的项目副本 |
| 复杂度 | 低 | 中 |
业务场景
| 场景 | 推荐方案 |
|---|---|
| 修复紧急 bug 同时继续开发 | git worktree add 创建独立工作树 |
| 并行开发多个功能 | 为每个功能创建工作树 |
| 代码审查 | 创建临时工作树审查 PR |
| 版本对比测试 | 同时检出多个版本的工作树 |
| 长期实验 | 创建 detached HEAD 工作树 |
扩展阅读
🔗 上一章:11 - 变基进阶 | 下一章:13 - Git Hooks