[转载] 用 Git worktree 做并行开发,不再手忙脚乱
原文出处: https://barrd.dev/article/parallel-development-without-the-headaches-using-git-worktree/
作者: Dave(barrd)
原文发布日期: 2026-01-01
许可协议: 本文为其中文翻译,所有权利归原文作者所有。
引言
最近在折腾一个相当棘手的项目时,我接触到了 Git 的 worktree 功能。它让你可以同时在多个分支上工作,每个分支各自拥有一个目录,而它们共享同一套底层仓库历史。
一个直观的示意:
~/Herd/
├── my-project/ # 主 worktree,分支 `main`
│ └── .git/ # 主 git 目录
├── my-project-feature/ # 链接 worktree,分支 `feature/login-form`
└── my-project-hotfix/ # 链接 worktree,分支 `hotfix/payment-bug`
上面这些目录共享同一份提交历史,并且都链接到同一个 .git 对象数据库,尽管每个目录都有各自独立的工作区状态。
每个目录的行为都和一个普通 checkout 一样:照常编辑文件、提交、推送,只是不必再在单一工作区里不停地切换分支。
Git branch 与 worktree 的区别
传统上,在多个分支间切换意味着大量的 git checkout 和 git stash——不停保存现场、切换上下文,还得祈祷没弄丢什么重要的东西。这很容易迷失,尤其是当生产环境的 bug 打断你的思路时。有了 git worktree,你可以为任意分支(已有的或新建的)添加一个新工作目录,让各条工作流互不干扰。比如:
# 把已有分支添加为 worktree
git worktree add ../my-project-feature feature-branch
# 或者一步创建新分支 + worktree
git worktree add -b new-feature ../my-project-new-feature
这会在主项目同级的位置创建新目录,并 checkout 到你指定的分支。现在你可以在每个目录里独立地编辑、提交、推送,完全不影响主工作目录。
你的目录布局大概会是这样:
my-project/ # 主 worktree,分支 `main`
my-project-feature/ # worktree,分支 `feature-branch`
my-project-new-feature/ # worktree,分支 `new-feature`
一个重要的限制:同一个分支不能同时被多个 worktree checkout。每个 worktree 必须检出不同的分支。实际使用中,这反而促成一种清爽的心智模型——「一个任务、一个分支、一个目录」,让人不容易迷失方向。
实战示例:功能开发和紧急修复两头兼顾
来看一个真实场景:你正在开发一个结账功能,这时生产环境的 bug 突然冒出来了。
初始布局:
~/Herd/
└── shop/ # 主 worktree,分支 `main`
└── .git/
创建功能分支的 worktree:
cd ~/Herd/shop
git worktree add -b feature/checkout ../shop-checkout
新布局:
~/Herd/
├── shop/ # 主 worktree,分支 `main`
│ └── .git/
└── shop-checkout/ # 链接 worktree,分支 `feature/checkout`
接下来你可以在 shop-checkout 里安心开发结账功能,同时让 shop 停在 main 上,随时可以用来做快速审查。
生产环境出 bug 了,建一个 hotfix worktree
cd ~/Herd/shop
git worktree add -b hotfix/payment-fail ../shop-payment-hotfix
目录布局变成:
~/Herd/
├── shop/ # 主 worktree,分支 `main`
├── shop-checkout/ # 功能 worktree,`feature/checkout`
└── shop-payment-hotfix/ # hotfix worktree,`hotfix/payment-fail`
此时你可以:
- 在
shop-payment-hotfixworktree 里修复并测试生产 bug。 - 在
shop-checkoutworktree 里继续迭代feature/checkout。 - 让
shop空闲在main上,专门用于合并与 code review。
如何把 worktree 的分支合并到其他分支
从 worktree 分支发起合并,和普通的 Git merge 没有任何区别,只是上下文更清晰,因为每个分支都住在自己的目录里。下面是把功能分支合入 main 的典型流程:
- 在功能 worktree 里完成工作并提交。
- 切换到主 worktree 目录:
cd ../my-project && git checkout main
- 合并功能分支:
git merge feature-branch
- 解决冲突(如果有),然后推送。
正因为每个 worktree 都专属于一个分支,你很难再把提交落错分支,也不至于在 hotfix 打断功能开发时丢了现场……当然,这是理论上的。😉
查看当前的 worktree
在开始删除或清理之前,先看看 Git 目前都知道哪些 worktree:
git worktree list
示例输出:
/Users/barrd/Herd/shop 66c16256 [main]
/Users/barrd/Herd/shop-checkout 0c8ba118 [feature/checkout]
/Users/barrd/Herd/shop-payment-hotfix a16e4be2 [hotfix/payment-fail]
你可以在脑中把它映射成:
[main] → /home/user/Herd/shop
[feature/checkout] → /home/user/Herd/shop-checkout
[hotfix/payment-fail] → /home/user/Herd/shop-payment-hotfix
哪些分支被检出、检出到哪里,一目了然,也能避免去复用一个已被其他 worktree 占用的分支。
如何删除 worktree
一个 worktree 用完之后,最好及时清理。安全删除的前提是先提交或 stash 掉所有改动:
git worktree remove ../my-project-feature
只有干净的工作树(没有未提交改动、没有未跟踪文件)才能这样删除,除非加 --force;主 worktree 则永远无法被移除。
记住
删除 worktree 只是删掉工作目录,分支本身还在。删除前务必在该 worktree 里 git status 确认一下,以免弄丢未提交的工作。
用 prune 清理失效的 worktree
如果你是手动 rm 掉了 worktree 目录,Git 仍会在主仓库的 worktrees 目录下保留它的元数据。这时 git worktree list 会把对应条目标记为缺失。
清理这些失效条目:
git worktree prune
如果只想清理一段时间未使用的条目,可以加过期时间:
git worktree prune --expire 7.days.ago
--expire now 则立即清除所有失效元数据——如果你在本地开发环境里经常随手清掉旧目录,这招会很顺手。
写在最后
worktree 从 v2.5(大约 10 年前)起就已存在,而我从来没用过……但现在它彻底改变了我的工作流,尤其是在并行推进多个功能和应对紧急 hotfix 的时候。一切都各归其位,上下文切换减少了,stash 也成了罕物。
对于简单的、串行推进的工作,传统分支方式依然是首选;但如果你曾幻想自己能同时身处两地,不妨试试 git worktree。