Git worktree 怎么用?同时开发多个分支完整教程
无需重复克隆,在同一仓库中并行开发、修复 Bug 和测试版本
Git worktree 怎么用?同时开发多个分支完整教程
Git worktree 可以让一个 Git 仓库同时拥有多个工作目录,每个目录检出不同分支。这样,在功能开发尚未完成时遇到紧急 Bug,不必先提交半成品、执行 stash 或反复切换分支,而是可以在另一个目录中直接开始修复。
本文将从基本原理开始,完整讲解 worktree 的创建、查看、移动、锁定、删除、清理和故障恢复,并给出团队开发中常见的使用场景与注意事项。
|----------------------------------------------------------------------|
| 提示: 本文命令适用于 Git Bash、PowerShell 和大多数终端。示例中的目录路径和分支名称需要根据自己的项目替换。 |
一、为什么需要 Git worktree?
普通 Git 仓库通常只有一个工作目录。一个目录在同一时间只能显示一个分支的文件,因此切换任务时,往往需要先处理当前目录中的未提交修改。
例如,你正在 feature/payment 分支重构支付模块,代码还没有完成。这时线上 main 分支出现紧急问题,需要立刻修复。传统做法通常有三种:先提交一个临时版本、先执行 git stash,或者重新 clone 一份仓库。
worktree 提供了第四种方式:保留当前目录和所有未提交修改,在旁边创建另一个与同一仓库关联的目录,并在新目录中检出 hotfix 分支。两个目录可以同时打开、同时编译,也可以分别在不同 IDE 窗口中开发。

图 1 功能开发与紧急修复可以在两个工作目录中并行进行
二、Git worktree 到底是什么?
一个普通的非裸仓库包含一个主工作区。执行 git worktree add 后,Git 会创建一个"链接工作区"。主工作区和所有链接工作区共享同一套仓库对象、提交历史、分支引用和远程仓库配置,但每个工作区都拥有独立的 HEAD、索引和工作文件。
因此,worktree 并不是完整复制仓库历史。它比重新 clone 更轻量,也不会产生多套互不关联的本地对象数据库。不过,每个工作区都会保存一份实际检出的项目文件,编译产物、依赖目录和 IDE 缓存也可能分别占用空间。

图 2 多个工作区共享仓库数据,但拥有独立的当前分支和工作文件
|--------------------------------------------------------------------------|
| 注意: 同一个本地分支默认不能同时在两个 worktree 中检出。Git 会主动阻止这种操作,避免两个目录同时修改同一分支而造成混乱。 |
三、worktree、stash 和重新 clone 应该怎么选?
|--------------|-------------------|--------------|------------------------|
| 方式 | 适合场景 | 优点 | 需要注意 |
| git switch | 当前修改已处理,可以直接切换任务 | 操作简单 | 未提交修改可能阻止切换 |
| git stash | 暂时收起少量未提交修改 | 不用新增目录 | 恢复时可能发生冲突,现场不够直观 |
| git worktree | 需要同时保留多个分支的完整工作现场 | 可以并行开发,切换成本低 | 每个目录仍会占用项目文件和构建空间 |
| 重新 clone | 需要完全独立的仓库配置或权限环境 | 隔离最彻底 | 重复下载历史,占用更多磁盘,远程配置可能不同 |
简单判断:只是短暂切换且修改不多,可以使用 stash;需要数小时或数天同时维护两个任务,worktree 通常更合适;需要完全隔离的远程地址、账号、Git 配置或实验环境时,再考虑重新 clone。
四、开始前的准备工作
1. 查看 Git 版本
先确认终端能够正常识别 Git。
2. 进入现有仓库
worktree 必须依附于一个已有 Git 仓库,因此需要先进入项目主目录。
cd D:/projects/shop-system
git status
3. 建议把新增工作区放在主目录旁边
假设主项目目录是 shop-system,可以把其他工作区命名为 shop-system-hotfix、shop-system-payment。这样目录关系清晰,也能避免把新工作区创建到原仓库内部。
|-------------------------------------------------------|
| 注意: 不要把链接工作区创建在主项目目录的子目录中,否则目录结构、构建工具和文件搜索容易互相干扰。 |
五、查看当前所有 worktree
在主工作区或任意链接工作区中,都可以执行下面的命令。
git worktree list
输出通常包含工作目录路径、当前提交和分支名称。
D:/projects/shop-system a12bc34 [main]
D:/projects/shop-system-payment f98de21 [feature/payment]
D:/projects/shop-system-hotfix 6ac103f [hotfix/order]
需要查看更多状态信息时,可以使用详细模式。
git worktree list --verbose
需要在脚本中稳定解析输出时,可以使用 porcelain 格式。
git worktree list --porcelain
六、创建 worktree 的常用方式
1. 为已有本地分支创建工作区
假设本地已经存在 feature/payment 分支,可以直接指定新目录和分支。
git worktree add ../shop-system-payment feature/payment
执行完成后,../shop-system-payment 会成为新的工作目录,并检出 feature/payment。原来的主目录不会切换分支。
2. 创建新分支并同时创建工作区
这是实际开发中最常用的方式。下面的命令从当前 HEAD 创建 hotfix/order 分支,并把它检出到新目录。
git worktree add -b hotfix/order ../shop-system-hotfix
如果希望明确从 main 分支创建新分支,可以在命令末尾指定起点。
git worktree add -b hotfix/order ../shop-system-hotfix main
-b 只会创建不存在的新分支。如果分支名称已经存在,命令会拒绝执行。
3. 根据目录名自动创建分支
省略分支参数时,Git 会尝试使用目录最后一部分作为分支名称,并从当前 HEAD 创建该分支。
git worktree add ../hotfix
这个命令会创建名为 hotfix 的分支并在 ../hotfix 中检出。虽然写法简短,但团队开发中建议显式写出分支名称和起点,减少误解。
4. 从远程分支创建工作区
先更新远程分支信息,再创建本地跟踪分支和工作目录。
git fetch origin
git worktree add --track -b feature/report ../shop-system-report origin/feature/report
创建成功后,feature/report 会跟踪 origin/feature/report,可以在新工作区中正常 pull 和 push。
5. 创建 detached HEAD 工作区
只是想查看旧版本、运行测试或对比代码,不准备直接在某个分支上提交时,可以创建分离头指针工作区。
git worktree add --detach ../shop-system-review v1.2.0
也可以指定某个提交 ID。
git worktree add --detach ../shop-system-review a12bc34
|---------------------------------------------------------|
| 注意: detached HEAD 中产生的提交没有本地分支长期指向。需要保留修改时,应及时创建分支。 |
git switch -c review/fix
七、完整实战:开发中途处理紧急 Bug
下面以一个常见场景演示完整流程。主工作区正在 feature/payment 分支开发,线上 main 分支突然出现订单金额计算错误。
第 1 步:确认主工作区当前状态
git status
git branch --show-current
当前未提交修改可以原样保留,不需要执行 stash。
第 2 步:更新远程 main
git fetch origin
第 3 步:从远程 main 创建紧急修复工作区
git worktree add -b hotfix/order-amount ../shop-system-hotfix origin/main
第 4 步:进入新目录并修复代码
cd ../shop-system-hotfix
git status
第 5 步:提交并推送修复
git add .
git commit -m "fix: 修复订单金额计算错误"
git push -u origin hotfix/order-amount
第 6 步:合并完成后删除临时工作区
cd ../shop-system
git worktree remove ../shop-system-hotfix
第 7 步:删除已经合并的本地分支
git branch -d hotfix/order-amount
此时原来的 shop-system 目录仍然停留在 feature/payment,未提交修改也保持原样,可以立即继续开发。

图 3 从创建到删除的 worktree 完整生命周期
八、在多个工作区之间切换
worktree 不需要使用 git switch 在多个任务之间来回切换。每个分支已经固定在各自目录中,所谓"切换"就是进入另一个目录,或者在 IDE 中切换项目窗口。
cd ../shop-system-payment
cd ../shop-system-hotfix
可以同时打开多个终端窗口,每个终端停留在不同 worktree。执行 git status 时,只会显示当前工作区自己的修改和暂存状态。
|-----------------------------------------------------------------------------------|
| 提示: 所有 worktree 共享分支引用和提交历史。因此,在一个工作区提交后,其他工作区立即能够看到该提交,但其他工作区的工作文件不会自动切换或改写。 |
九、删除 worktree
1. 正常删除干净的工作区
git worktree remove ../shop-system-hotfix
Git 只允许直接删除没有已跟踪修改、没有未跟踪文件的干净工作区。删除工作区不会自动删除它对应的分支。
2. 强制删除存在修改的工作区
git worktree remove --force ../shop-system-hotfix
|--------------------------------------------------------------|
| 注意: 强制删除会直接丢弃该工作区中的未提交文件。使用前应先执行 git status,确认没有需要保留的内容。 |
3. 删除对应分支
git branch -d hotfix/order-amount
只有在不再需要分支时才删除。分支尚未合并时,-d 会拒绝删除;确认必须删除时才使用 -D。
git branch -D hotfix/order-amount
十、移动 worktree 目录
需要修改链接工作区的位置时,优先使用 git worktree move,而不是直接在文件管理器中剪切目录。
git worktree move ../shop-system-payment ../worktrees/payment
主工作区不能通过该命令移动;包含子模块的链接工作区也存在移动限制。
手动移动后修复关联
如果已经手动移动了目录,Git 可能仍然记录旧路径,可以在移动后的工作区中执行修复。
git worktree repair
如果主工作区与多个链接工作区都被移动,可以从任意可用工作区指定新的目录进行修复。
git worktree repair ../worktrees/payment ../worktrees/hotfix
十一、锁定和解锁 worktree
如果链接工作区位于移动硬盘或网络共享目录中,设备暂时未挂载时,Git 可能把它判断为失效工作区。可以锁定它,阻止自动清理、移动或删除。
git worktree lock ../portable-project --reason "存放在移动硬盘"
重新连接设备后,可以解锁。
git worktree unlock ../portable-project
查看锁定原因时使用详细列表。
git worktree list --verbose
十二、prune 清理残留元数据
正常情况下应使用 git worktree remove 删除工作区。如果直接在文件管理器中删除目录,仓库内部仍可能保留该 worktree 的管理信息。此时可以使用 prune 清理。
先预览将要清理的内容
git worktree prune --dry-run --verbose
执行清理
git worktree prune --verbose
|----------------------------------------------------------------------|
| 注意: prune 用于删除已经不存在的工作区元数据,不会替代正常的 remove 流程。被锁定的工作区不会被普通清理操作移除。 |
十三、常见报错与解决方法
1. 分支已经在其他 worktree 中检出
fatal: 'feature/payment' is already checked out at 'D:/projects/shop-system-payment'
这是 Git 的安全限制。先通过列表确认该分支所在目录,然后直接使用现有 worktree。
git worktree list
需要并行进行另一组修改时,创建一个不同名称的新分支。
git worktree add -b feature/payment-test ../shop-system-payment-test feature/payment
|----------------------------------------------------------------------------|
| 注意: 虽然 --force 可以绕过部分检出保护,但让同一分支同时出现在两个工作区容易造成提交和工作文件状态混乱,不建议在日常开发中使用。 |
2. 目标目录已经存在且不为空
fatal: '../shop-system-hotfix' already exists
换一个空目录,或者确认旧目录确实不再需要后手动处理。不要为了省事直接覆盖包含文件的目录。
3. 找不到远程分支
fatal: invalid reference: origin/feature/report
先更新远程引用并确认分支名称。
git fetch --all --prune
git branch -r
4. 删除时提示包含修改或未跟踪文件
fatal: working trees containing modified or untracked files cannot be removed
进入该目录检查状态,提交、暂存或删除不需要的文件后再移除。
cd ../shop-system-hotfix
git status
确认内容全部不需要时,再返回其他工作区强制删除。
git worktree remove --force ../shop-system-hotfix
5. 手动删目录后仍显示 prunable
先预览再清理残留记录。
git worktree list --verbose
git worktree prune --dry-run --verbose
git worktree prune --verbose
6. 移动目录后提示不是有效仓库
worktree 的关联路径已经失效,进入移动后的目录执行 repair。
git worktree repair
十四、在 IDEA 中使用 worktree
每个 worktree 都是一个正常的项目目录,可以在 IDEA 中分别打开。对于 Spring Boot、Maven 或 Gradle 项目,建议把不同工作区放在同一级目录,并分别使用独立窗口。
- 在主工作区窗口继续开发 feature 分支。
- 在第二个 IDEA 窗口打开 hotfix 工作区。
- 每个窗口分别提交代码,不要在错误目录中执行命令。
- Maven target、Gradle build、node_modules 和 IDE 索引通常会在各工作区分别生成。
- 环境变量、端口、数据库和 Redis 配置可能相同,同时运行多个项目实例时需要避免端口冲突。
|-----------------------------------------------------------------------------------------------------------|
| 提示: 判断当前 IDEA 窗口对应哪个分支时,不要只看窗口标题。可以在内置终端执行 git branch --show-current 和 git rev-parse --show-toplevel。 |
git branch --show-current
git rev-parse --show-toplevel
十五、worktree 的磁盘占用与性能
多个 worktree 共享 Git 对象数据库,因此不会像多次 clone 那样重复保存完整提交历史。不过,每个工作区都拥有自己的项目文件,构建目录和第三方依赖也可能重复。
- Java 项目的 target、build、.gradle 可能在每个工作区分别产生。
- 前端项目的 node_modules 往往体积较大,多个工作区会明显增加磁盘占用。
- IDEA 会为不同目录建立索引,首次打开可能再次扫描项目。
- Docker Compose、数据库端口和服务端口需要为并行运行分别配置。
因此,worktree 节省的是仓库历史和任务切换成本,不代表新增工作区完全不占磁盘。完成临时任务后及时删除,可以保持目录整洁。
十六、进阶:为不同 worktree 设置独立配置
Git 配置默认在所有 worktree 之间共享。确实需要为某个工作区设置独立配置时,可以启用 worktreeConfig 扩展。
git config extensions.worktreeConfig true
然后在当前工作区写入专属配置。
git config --worktree user.name "Hotfix Bot"
git config --worktree user.email "hotfix@example.com"
|------------------------------------------------------------------------|
| 注意: 这是进阶功能。启用前应确认团队使用的 Git 版本足够新,并清楚哪些配置应该共享、哪些配置应该独立。普通开发通常不需要修改。 |
十七、推荐的目录结构和命名方式
可以为同一仓库建立一个父目录,把主工作区和链接工作区并列放置。
D:/projects/shop-system/
D:/projects/shop-system-feature-payment/
D:/projects/shop-system-hotfix-order/
D:/projects/shop-system-review-v1.2/
目录名称应能直接看出用途,分支名称仍按照团队规范使用 feature/、hotfix/、release/ 等前缀。
- 临时工作区完成后及时 remove。
- 创建时显式指定新分支和起点。
- 不要在主仓库内部创建链接工作区。
- 不要让同一个分支同时出现在多个工作区。
- 执行提交、重置和删除前,先检查当前目录与当前分支。
十八、常用命令速查表
|----------------------|--------------------------------------------|
| 功能 | 命令 |
| 查看全部工作区 | git worktree list |
| 查看详细状态 | git worktree list --verbose |
| 为已有分支创建工作区 | git worktree add <目录> <分支> |
| 创建新分支和工作区 | git worktree add -b <新分支> <目录> <起点> |
| 创建 detached HEAD 工作区 | git worktree add --detach <目录> <提交或标签> |
| 移动链接工作区 | git worktree move <旧目录> <新目录> |
| 删除干净工作区 | git worktree remove <目录> |
| 强制删除工作区 | git worktree remove --force <目录> |
| 锁定工作区 | git worktree lock <目录> |
| 解锁工作区 | git worktree unlock <目录> |
| 预览残留清理 | git worktree prune --dry-run --verbose |
| 清理残留元数据 | git worktree prune --verbose |
| 修复移动后的关联 | git worktree repair |
十九、总结
Git worktree 的核心价值不是替代分支,而是让多个分支同时拥有各自独立的工作目录。它特别适合"功能开发尚未完成,突然需要修复 Bug""同时运行两个版本进行对比""一边开发一边执行长期测试"等场景。
最常用的操作只有三个:使用 git worktree add 创建,使用 git worktree list 查看,任务完成后使用 git worktree remove 删除。掌握这条主线后,再根据需要学习 move、lock、prune 和 repair 即可。
|-----------------------------------------------------------------------------------------------|
| 提示: 使用 worktree 前先确认目录和分支;删除前先检查未提交修改。只要保持清晰的目录命名和及时清理习惯,多个任务并行开发会比反复 stash 和 switch 更直观。 |
参考资料
Git 官方文档:git-worktree - Manage multiple working trees
Pro Git:Getting Started - What is Git?