使用 Git worktree 轻松实现并行开发
摘要
文章介绍了 Git 的 worktree 功能,该功能允许开发者在不同的目录中同时处理多个分支,从而提升并行开发任务的工作流程效率。
暂无内容
查看缓存全文
缓存时间: 2026/08/24 01:43
# 使用 Git worktree 轻松实现并行开发 : barrd.dev
来源: https://barrd.dev/article/parallel-development-without-the-headaches-using-git-worktree/
预计阅读时间约 10 分钟,共 1916 字。
## 引言
最近在捣鼓一个棘手项目时,我发现了 Git 的 `worktree` 功能。这个工具允许你同时处理多个分支,每个分支拥有独立的工作目录,同时共享同一个底层仓库历史。
简单示意图:
``
~/Herd/
├── my-project/ # 主工作树,分支 `main`
│ └── .git/ # 主 git 目录
├── my-project-feature/ # 关联工作树,分支 `feature/login-form`
└── my-project-hotfix/ # 关联工作树,分支 `hotfix/payment-bug`
``
上述所有目录共享相同的提交历史,并链接到同一个 `.git` 对象数据库(https://github.blog/open-source/git/gits-database-internals-i-packed-object-store),尽管每个目录都有自己的工作目录状态。
每个目录的作用就像普通的代码检出,你可以照常编辑文件、提交和推送,同时避免了在单一工作树中不断切换分支的麻烦。
## Git 分支与工作树的区别
Git 标志Git 版本控制标志显示为黑色倾斜方块内的分支图。(https://git-scm.com/)传统上,处理多个分支意味着需要频繁执行 `git checkout` 和 `git stash`,不断保存进度、切换上下文,并担心不会丢失重要数据。尤其是在生产环境 bug 打断工作流时,很容易迷失方向。而 `git worktree` 允许你为任何分支(现有或新建)添加新的工作目录,并将各工作流保持独立。例如:
``
# 将现有分支添加为工作树
git worktree add ../my-project-feature feature-branch
# 或一步到位创建新分支和工作树
git worktree add -b new-feature ../my-project-new-feature
``
这会在主项目同级目录创建新目录,检出到你指定的分支。现在你可以在各个目录中独立编辑文件、提交和推送,而无需触碰主工作目录。
配置示例:
``
my-project/ # 主工作树,分支 `main`
my-project-feature/ # `feature-branch` 的工作树
my-project-new-feature/ # `new-feature` 的工作树
``
重要限制:同一分支不能同时检出到多个工作树。每个工作树必须检出唯一分支。实践中,这促进了"一个任务、一个分支、一个目录"的整洁映射,便于心智定位。
## 实践案例:同时处理功能与热修复
现实场景:你正在开发结账功能时,生产环境突然出现 bug。
初始布局:
``
~/Herd/
└── shop/ # 主工作树,分支 `main`
└── .git/
``
创建功能工作树:
``
cd ~/Herd/shop
git worktree add -b feature/checkout ../shop-checkout
``
新布局:
``
~/Herd/
├── shop/ # 主工作树,分支 `main`
│ └── .git/
└── shop-checkout/ # 关联工作树,分支 `feature/checkout`
``
你可以在 `shop-checkout` 中开发结账功能,同时保持 `shop` 在 `main` 分支以便快速审查。
### 生产环境 bug 出现,创建热修复工作树
``
cd ~/Herd/shop
git worktree add -b hotfix/payment-fail ../shop-payment-hotfix
``
布局变为:
``
~/Herd/
├── shop/ # 主工作树,分支 `main`
├── shop-checkout/ # 功能工作树,`feature/checkout`
└── shop-payment-hotfix/ # 热修复工作树,`hotfix/payment-fail`
``
此时你可以:
- 在 `shop-payment-hotfix` 工作树中修复并测试生产 bug。
- 在 `shop-checkout` 工作树中继续迭代 `feature/checkout`。
- 保持 `shop` 在 `main` 分支空闲,用于合并和代码审查。
## 如何将工作树合并到其他分支
合并工作树分支的更改与普通 Git 合并相同,但由于每个分支位于独立目录,上下文更清晰。将功能分支合并到 `main` 的典型流程:
1. 在功能工作树中完成工作并提交更改。
2. 切换到主工作树目录:
``
cd ../my-project && git checkout main
``
3. 合并功能分支:
``
git merge feature-branch
``
4. 解决冲突,然后推送。
由于每个工作树专用于单一分支,大大降低了误提交到错误分支或在热修复中断功能工作时丢失进度的风险...当然,这只是理论。😉
## 查看当前工作树
在删除或清理之前,先了解 Git 当前已知的工作树:
``
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
``
现在可以清晰看出哪些分支已检出及其位置,避免重复使用已关联到其他工作树的分支。
## 如何删除工作树
完成工作树使用后,建议及时清理。安全操作的前提是已提交或暂存更改:
``
git worktree remove ../my-project-feature
``
此命令仅适用于"干净"的工作树(无未提交更改或未跟踪文件),除非使用 `--force` 参数,且不能删除主工作树。
**注意**:删除工作树只会移除工作目录,不会删除分支本身。删除前务必在该工作树中使用 `git status` 检查,避免丢失未提交的工作。
## 使用 prune 清理过期工作树
如果你手动删除了工作树目录,Git 仍会在主仓库的 `worktrees` 目录中保留其元数据。此时 `git worktree list` 会显示标记为缺失的条目。
可使用以下命令清理:
``
git worktree prune
``
若仅清理闲置一段时间的条目,可添加过期时间:
``
git worktree prune --expire 7.days.ago
``
使用 `--expire now` 会立即删除所有过期工作树元数据,这在本地开发环境中频繁清理旧目录时非常方便。
## 总结思考
Git worktree 功能自 `v2.5` 版本(约十年前)就已存在,而我从未使用过...但它现在彻底改变了我的工作流,尤其是在并行处理多个功能和紧急热修复时。它将所有元素模块化,减少上下文切换,使得 stash 操作变得罕见。
对于简单的线性工作,传统分支仍是最佳选择。但如果你曾希望同时处理多项任务,不妨尝试 `git worktree`。
如果你有常用的工作流变体,请联系我(https://barrd.dev/contact/)分享交流。
// 文章结束
## 文章信息
- Git 数据库内部原理 (https://github.blog/open-source/git/gits-database-internals-i-packed-object-store)(github.blog)
- Git Worktree 文档 (https://git-scm.com/docs/git-worktree)(git-scm.com)
### 相关文章/页面
- Git switch – 分支错误时的 stash 替代方案 (https://barrd.dev/article/git-switch-a-replacement-for-stash/)(文章)
- 从 Laravel Herd 中移除未使用的 PHP 版本 (https://barrd.dev/article/remove-unused-php-versions-from-laravel-herd/)(文章)
- 在保留 Valet 和 PHP Monitor 的同时使用 Laravel Herd (https://barrd.dev/article/using-laravel-herd-whilst-keeping-valet-and-php-monitor/)(文章)
- Starship,超快的跨 Shell 提示符 (https://barrd.dev/article/starship-blazing-fast-cross-shell-prompt/)(文章)
Dave(又名 'barrd')的图片 (https://barrd.dev/app/uploads/Dave-Chocolate-Path-Bristol-aspect-ratio-768-768-1.jpg.webp)Dave 是常居布里斯托的苏格兰移民,拥有 20 余年网页开发经验。热爱弹吉他、阅读、观看科幻作品和钻研科技。
了解更多关于 Dave 的信息 (https://barrd.dev/article/parallel-development-without-the-headaches-using-git-worktree/#author-popup)
相似文章
@github: Git worktrees自2015年以来就已存在,但如今它们重新兴起。@cassidoo解释了它们是什么以及为什么AI时代……
Git worktrees(Git工作树)是自2015年起就存在的功能,随着AI时代并行工作的需求增加,它们正变得越来越受欢迎。本文解释了工作树是什么、它们与分支的区别,以及为什么它们能减少开发者的上下文切换开销。
@mogician301: https://x.com/mogician301/status/2071841989751112147
文章介绍了 git worktree 在 AI 时代进行多任务并行开发的优势,以及作者开发的 cc-launch 工具如何通过自动初始化、统一管理等解决 worktree 的使用痛点,提升开发效率。
Git worktrees 并非编码代理的隔离边界
本文解释了 Git worktrees 并未为 AI 编码代理提供真正的隔离,因为它们与父仓库共享钩子、配置和引用,从而允许代理在主机上执行任意代码。基准测试表明,适当隔离的克隆具有可比的性能,挑战了 worktrees 既隔离又廉价的观点。
Treebar
Treebar 是一个开发者工具,提供所有活跃 Git 工作树的统一视图,帮助简化代码管理。
Rift:Git Worktrees 的更优替代方案
Rift 是一个命令行工具,提供比 Git worktrees 更好的替代方案,通过写时复制快照在 Linux 的 btrfs 和 macOS 的 APFS 上实现快速创建工作区。