什么是 git worktrees,为什么要用它们?
What are git worktrees, and why should I use them?
Git 的 worktree(工作树)功能自 2015 年已存在,近期因 AI 驱动的并行开发需求而重新受到关注。传统上下文切换依赖 git stash 和分支操作,需多次切换分支、暂存和恢复工作,心智负担高。Worktree 允许在同一仓库的不同目录中同时检出多个分支,无需 stash 或切换上下文,可直接并行处理任务。其缺点包括每个 worktree 需独立安装项目依赖、需手动管理文件夹、全局 .gitignore 配置要求,以及同一分支不能在两个 worktree 中同时检出。GitHub Copilot 应用已默认支持 worktree 作为新会话的工作空间。
最近 Git 领域的热门话题似乎是 worktree(工作树)的概念。这……有点意思,因为 worktree 早在 2015 年就已经存在了。不过,它们确实很酷,你可能会好奇为什么要用它们、它们与分支有何不同,以及为什么突然变得如此流行。我们来聊聊吧!
用分支和 stash 进行上下文切换
假设你生活在一个没有 worktree 的世界里,正在处理一个任务,突然一个紧急 bug 找上门来,你不得不切换上下文。首先,你可能会 stash 当前的工作:
git stash "wip feature login"
然后切换到主分支并更新:
git checkout main
git pull origin main
接着创建一个 bug 修复分支:
git checkout -b hotfix-bug
然后修复所有问题,提交并推送分支:
git add .
git commit -m "fix broken submit button"
git push origin hotfix-bug
合并 pull request 后,你回到电脑前,拉取 main 分支并删除 bug 分支:
git checkout main
git pull origin main
git branch -d hotfix-bug
最后回到你正在开发的功能分支:
git checkout feature-login
git stash pop
呼。刚才我们说到哪了?来回切换、重新加载文件、根据变更重新安装 node_modules 等等,这些心智负担非常重。上下文切换的代价很大。
这只是一个基本示例,但有时开发者会用更复杂的 git stash 命令,甚至对同一个仓库进行多次克隆(我也干过这种事)来应对这种混乱。直到……worktree 的出现!
用 worktree 进行上下文切换
使用 worktree,你永远不需要离开当前分支,也无需 stash,而且原始功能的编辑器上下文保持不变。
git worktree add ../hotfix-workspace -b hotfix-bug main
这会立即创建一个名为 hotfix-workspace 的兄弟文件夹,基于 main 分支,并检出一个名为 hotfix-bug 的新分支。现在你可以在新的编辑器窗口中打开该文件夹(或 cd 进入),修复 bug。你原来的编辑器窗口保持原样。
cd ../hotfix-workspace
# ...修复修复修复...
git add .
git commit -m "fix broken submit button"
git push origin hotfix-bug
像之前一样在线合并 pull request,合并后直接删除临时文件夹即可。
cd ../main-project
git worktree remove ../hotfix-workspace
这流畅多了!完全没有 stash 冲突的风险,不会干扰编辑器,你可以真正并行工作。
那么……为什么是现在?
很长一段时间里,worktree 相对不为人知。大多数开发者从未听说过它们,要么是因为 Git GUI 不支持(或将其视为二等公民),要么是因为他们通常遵循已知的模式:功能分支 → 工作 → PR → 合并 → 重复。
现在,我们作为开发者的工作方式已经改变。AI 让我们比软件开发历史上任何时候都更频繁地并行工作。开发者同时运行大量会话,“代码审查文化”正在超越“代码编写文化”。Agent 和人类可以通过 worktree 实现更多并行工作。这是 GitHub Copilot 应用以及许多其他现代工具的默认模式。
有什么缺点?
Worktree 确实解决了很多问题,但也有一些需要注意的地方。
- 依赖膨胀:每个 worktree 文件夹都需要项目依赖的独立副本。如果你在多个 worktree 中运行
npm install或pip install,你的电脑可能会很快变得非常满。 - 文件夹管理:你需要删除 worktree 文件夹,以免父目录随时间变得杂乱。像 GitHub Copilot 这样的应用通常会为你处理这一点,但如果你自己在终端操作,可能还是需要手动处理。
- 全局 .gitignore 要求:如果你在主仓库目录内创建 worktree 文件夹,必须手动将它们添加到
.gitignore中,以免意外被跟踪。你可以将这些 worktree 放在主仓库之外(许多应用默认这样做),但这一点值得注意。 - 单分支限制:Git 会阻止你在两个不同的 worktree 中同时检出完全相同的分支,以防止数据损坏。
如何在 GitHub Copilot 应用中使用 worktree?
好问题!很棒的是……它们开箱即用。当你打开应用时,主屏幕上有一个下拉菜单,询问你希望在哪里运行新会话。默认选项是新的 worktree。然后,启动新会话后,你可以点击应用顶部的会话名称,就会看到(有趣的)自动生成的 worktree 名称、它的路径、所属项目,以及你所做更改的详细信息。简单又轻松!
我应该使用 worktree 吗?
我会给你一个最资深开发者的回答:看情况!你可能更喜欢某种工作方式。你可能并行工作不多,更喜欢分支和 stash 的心智模型。你可能从现在开始只用 worktree。你可能两者都想用!世界是你的牡蛎,你现在就可以在 GitHub Copilot 应用中尝试所有方式。
原文《What are git worktrees, and why should I use them?》首发于 The GitHub Blog。