什么是Git Worktree
Git Worktree是Git 2.5(2015年发布)引入的一项内置特性,允许在同一个本地仓库中同时检出多个分支到不同的目录,每个目录拥有独立的工作区(working tree)和暂存区(index),但共享同一份.git对象数据库。
简单来说,一个git仓库可以在不同文件系统路径下同时"展开"多个分支的代码,互不干扰,而无需克隆多个副本。
解决的问题与核心优势
传统方式的痛点
在没有Git Worktree之前,如果需要同时处理多个分支,常见的做法有:
- 频繁切换分支:
git stash→ 切换 → 工作 → 切换回来 →git stash pop,流程繁琐且容易出错。 - 克隆多个仓库副本:在不同目录分别
git clone同一个仓库,但会浪费磁盘空间,且各副本的对象数据库相互独立,Push/Pull 操作无法共享缓存。 - 中断当前工作:处理紧急的
hotfix时,必须先提交或丢弃当前未完成的工作,打断开发节奏。
Git Worktree 的显著优点
| 优点 | 说明 |
|---|---|
| 多分支并行开发 | 同时在多个目录打开不同分支的代码,互不影响 |
| 零重复磁盘空间 | 所有worktree共享同一个.git对象库,无数据冗余 |
无需stash | 切换任务时不必暂存当前修改,各工作区状态完全独立 |
| 快速响应紧急任务 | 可立即在新worktree中处理hotfix,无须中断当前开发 |
原生git支持 | 无需安装任何插件,所有git子命令均正常工作 |
| 支持编辑器并行打开 | 可在多个编辑器窗口中分别打开不同worktree目录 |
基本命令速查
| 命令 | 说明 |
|---|---|
git worktree add <路径> <分支> | 创建新的worktree并检出指定分支 |
git worktree add -b <新分支> <路径> | 创建新分支并同时创建对应worktree |
git worktree list | 列出所有worktree |
git worktree remove <路径> | 删除指定worktree |
git worktree prune | 清理失效的worktree记录 |
git worktree move <路径> <新路径> | 移动worktree到新位置 |
git worktree lock <路径> | 锁定worktree,防止被自动清理 |
git worktree unlock <路径> | 解锁worktree |
使用示例
创建一个Worktree
假设当前仓库主目录为/project/my-app,正在main分支上开发,需要同时处理feature/user-auth分支。
基于已有分支创建worktree:
# 进入主仓库目录
cd /project/my-app
# 创建 worktree,检出已有分支
git worktree add ../my-app-feature feature/user-auth
执行后,/project/my-app-feature目录将包含feature/user-auth分支的完整代码,可以直接开始工作。
基于当前HEAD创建新分支并同时建立worktree:
# -b 表示创建新分支
git worktree add -b hotfix/payment-bug ../my-app-hotfix main
此命令基于main分支创建名为hotfix/payment-bug的新分支,并将其检出到../my-app-hotfix目录。
查看所有worktree:
git worktree list
输出示例:
/project/my-app abc1234 [main]
/project/my-app-feature def5678 [feature/user-auth]
/project/my-app-hotfix ghi9012 [hotfix/payment-bug]
在Worktree中提交修改
在新的worktree目录中,所有常规git操作均正常使用,与普通仓库无异:
# 进入 worktree 目录
cd ../my-app-hotfix
# 修改代码后正常提交
git add .
git commit -m "fix: 修复支付流程空指针异常"
# 推送到远端
git push origin hotfix/payment-bug
在某个worktree中提交的代码,在其他worktree执行git log或git fetch时同样可见,因为它们共享同一个.git对象库。
将修改合并回主分支
完成worktree中的工作后,合并回目标分支的流程与普通分支合并完全一致。
方式一:在主worktree中执行合并
# 回到主工作目录
cd /project/my-app
# 合并 hotfix 分支
git merge hotfix/payment-bug
# 或使用 rebase
git rebase hotfix/payment-bug
方式二:通过Pull Request/Merge Request合并
直接在代码托管平台(GitHub、GitLab等)发起PR/MR,与普通分支流程完全相同。
删除Worktree
任务完成后,应及时删除不再需要的worktree,释放磁盘空间和git内部记录。
# 方式一:使用 git 命令删除(推荐)
git worktree remove ../my-app-hotfix
# 方式二:如果 worktree 中有未提交的修改,需要强制删除
git worktree remove --force ../my-app-hotfix
git worktree remove会同时删除目录和git内部的worktree记录。如果只是手动删除了目录(rm -rf),则需要执行git worktree prune来清理失效的内部记录。
# 清理因手动删除目录而残留的 worktree 记录
git worktree prune
删除worktree后,对应的分支本身不会被删除,仍然可以通过git branch查看。若需要同时删除分支:
git branch -d hotfix/payment-bug
完整工作流示意
注意事项与最佳实践
注意事项
同一分支不能被多个Worktree同时检出
Git不允许同一分支被多个worktree同时检出。如果尝试在新的worktree中检出一个已经在其他worktree中使用的分支,git会报错:
fatal: 'feature/user-auth' is already checked out at '/project/my-app-feature'
需要先删除占用该分支的worktree,或检出到其他分支才能操作。
Worktree目录的位置建议放在仓库目录外
推荐将worktree目录放在主仓库目录的同级或上级路径下,而不是放在主仓库目录内部。否则主仓库的.gitignore配置可能需要额外处理,也容易造成混淆:
# 推荐:放在同级目录
git worktree add ../my-app-feature feature/user-auth
# 不推荐:放在主仓库目录内部
git worktree add ./worktrees/feature feature/user-auth
裸仓库(Bare Repository)是管理Worktree的最佳搭档
对于纯粹以worktree为主要工作方式的场景,可以使用裸仓库(--bare)作为.git数据存储中心,完全通过worktree操作代码。这样不会有"主工作区"的概念,所有分支均通过独立worktree检出:
# 克隆为裸仓库(只有 .git 内容,无工作文件)
git clone --bare https://github.com/your/repo.git my-repo.git
# 进入裸仓库目录
cd my-repo.git
# 为每个需要工作的分支创建 worktree
git worktree add ../my-repo-main main
git worktree add ../my-repo-feature feature/user-auth
.git文件而非目录
在worktree目录中,.git不是一个目录,而是一个指向主仓库.git/worktrees/<name>的文件:
# worktree 目录内的 .git 文件内容示例
gitdir: /project/my-app/.git/worktrees/my-app-feature
因此,直接切换worktree目录下的分支(git checkout other-branch)是不被允许的(因为该分支可能已被其他worktree占用),需要使用git worktree命令管理。
注意git stash的作用域
git stash的内容存储在.git对象库中,因此在任意一个worktree中执行git stash,其他worktree都可以通过git stash list看到。这既是特性也可能造成混乱,建议为stash添加描述性消息:
git stash push -m "feature-auth: 未完成的表单验证逻辑"
最佳实践
1. 统一命名规范
建议worktree目录名与分支名保持一致,便于识别:
# 分支名:feature/user-auth
# worktree 目录名:my-app-feature-user-auth
git worktree add ../my-app-feature-user-auth feature/user-auth
2. 及时清理废弃的Worktree
分支合并或任务完成后,及时执行git worktree remove清理,保持工作环境整洁:
git worktree list # 查看现有 worktree
git worktree remove <路径> # 删除指定 worktree
git worktree prune # 清理失效记录
3. 搭配tmux或多终端分屏使用
将Git Worktree与tmux分屏结合,可以在一个终端中同时监控多个worktree的状态,如运行不同的测试或构建命令,效率更高。
4. Hotfix 标准流程建议
# Step 1: 从 main 创建 hotfix worktree
git worktree add -b hotfix/issue-123 ../app-hotfix main
# Step 2: 修复问题并提交
cd ../app-hotfix
# ... 修改代码 ...
git commit -am "fix: 修复 issue-123"
# Step 3: 推送并发起 PR
git push origin hotfix/issue-123
# Step 4: PR 合并后清理
git worktree remove ../app-hotfix
git branch -d hotfix/issue-123
5. 与CI/CD集成
在CI/CD脚本中,可以利用worktree在同一个克隆的仓库目录下并行检出多个分支进行构建/测试,避免重复克隆带来的网络和磁盘开销。
总结
Git Worktree是一个被很多开发者忽视但极为实用的特性。它从根本上改变了多分支并行工作的方式——不再需要stash、不再需要克隆多份仓库、不再受"只能检出一个分支"的约束。结合VS Code的多窗口或多根工作区能力,Git Worktree可以显著提升在多任务并行场景下的开发效率,特别适合以下场景:
- 主线开发与
hotfix并行处理 Code Review时需要在本地运行对方分支的代码- 需要对比两个分支的运行行为差异
- 大型项目中多个
feature分支的同步推进