Skip to main content

什么是Git Worktree

Git WorktreeGit 2.52015年发布)引入的一项内置特性,允许在同一个本地仓库中同时检出多个分支不同的目录,每个目录拥有独立的工作区(working tree)和暂存区(index),但共享同一份.git对象数据库。

简单来说,一个git仓库可以在不同文件系统路径下同时"展开"多个分支的代码,互不干扰,而无需克隆多个副本。

解决的问题与核心优势

传统方式的痛点

在没有Git Worktree之前,如果需要同时处理多个分支,常见的做法有:

  1. 频繁切换分支git stash → 切换 → 工作 → 切换回来 → git stash pop,流程繁琐且容易出错。
  2. 克隆多个仓库副本:在不同目录分别git clone同一个仓库,但会浪费磁盘空间,且各副本的对象数据库相互独立,Push/Pull 操作无法共享缓存。
  3. 中断当前工作:处理紧急的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
tip

在某个worktree中提交的代码,在其他worktree执行git loggit fetch时同样可见,因为它们共享同一个.git对象库。

将修改合并回主分支

完成worktree中的工作后,合并回目标分支的流程与普通分支合并完全一致。

方式一:在主worktree中执行合并

# 回到主工作目录
cd /project/my-app

# 合并 hotfix 分支
git merge hotfix/payment-bug

# 或使用 rebase
git rebase hotfix/payment-bug

方式二:通过Pull Request/Merge Request合并

直接在代码托管平台(GitHubGitLab等)发起PR/MR,与普通分支流程完全相同。

删除Worktree

任务完成后,应及时删除不再需要的worktree,释放磁盘空间和git内部记录。

# 方式一:使用 git 命令删除(推荐)
git worktree remove ../my-app-hotfix

# 方式二:如果 worktree 中有未提交的修改,需要强制删除
git worktree remove --force ../my-app-hotfix
caution

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 Worktreetmux分屏结合,可以在一个终端中同时监控多个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分支的同步推进