我坚信 Git 工作树是 Git 中最被低估的功能之一。我多年来一直忽略它们,因为我不理解它们,也不知道如何将其融入我的工作流程。
但随着我开始使用 LLM 编码工具进行更多的并行工作,这种情况发生了改变。能够同时处理多个分支是一个巨大的变革。
没有 Git 工作树,在同一个仓库中同时处理多个分支是一件很痛苦的事。要么采用串行方式:暂存你的更改,切换上下文,然后祈祷没有搞坏任何东西。或者更糟的是,直接用“WIP”消息提交未完成的工作(看着你呢,过去的我)。或者,你可以拥有同一个仓库的多个克隆,但这管理起来很麻烦,并且会占用大量磁盘空间。
Git 工作树解决了这个问题。它们允许你在不同的目录中同时检出多个分支,所有这些目录都共享同一个 Git 数据库(即 .git 目录)。对我来说,这意味着我可以在一个终端中处理一个功能,在另一个终端中审查 PR,让 Claude Code 在另一个终端中处理另一个功能,并且所有这些工作都共享相同的 Git 历史记录。
但问题是:手动创建工作树很繁琐。你需要记住把它们放在哪里,如何命名,以及之后清理它们。此外,默认情况下,除非你指定其他目录,否则 Git 工作树会在仓库的根目录中创建。
我想要一些更简单的东西。我想要一个在任何仓库中都能工作的东西。无需设置,没有配置文件,只有合理的默认值。
欢迎使用 tree-me
我构建了 tree-me,这是一个对 Git 原生工作树命令的最小化封装。它在让 Git 处理所有复杂性的同时,增加了组织性规范。
你可以不用这样:
|
|
而是这样做:
|
|
工作原理
tree-me 使用类似 Git 的子命令并遵循约定,因此您无需思考:
- 根据 Git 远程仓库自动检测仓库名称
- 自动检测默认分支(检查 origin/HEAD,回退到 main)
- 按仓库组织:
$WORKTREE_ROOT/<repo-name>/<branch-name> - 将所有验证、错误和边缘情况委托给 Git 处理
- PR 支持:使用 Git 的原生 PR 引用获取 GitHub PR(需要 gh CLI)
- 自动 CD:创建后自动切换到工作树目录
- 选项卡补全:在 bash/zsh 中补全命令和分支名称
命令:
|
|
示例:
|
|
约定
tree-me 是 Git 原生命令的最小化封装。适用于任何仓库、任何语言、任何设置。唯一的约定是工作树的存放位置和命名方式。
希望工作树放在不同的位置?设置 WORKTREE_ROOT 环境变量。需要从 develop 而不是 main 创建分支?将其作为参数传递:tree-me create my-feature develop。这是一个有逃生舱口的约定。
设置
要启用自动 cd 和选项卡补全,请将以下内容添加到您的 ~/.bashrc 或 ~/.zshrc 中:
|
|
这使得 tree-me create、tree-me checkout 和 tree-me pr 能够自动 cd 到工作树目录。它还为命令和分支名称启用了选项卡补全(试试 tree-me rm <TAB>)。
完整实现请查看 github.com/haacked/dotfiles/blob/main/bin/tree-me。
PR 审查工作流
这是它大放异彩的地方。当你正深入开发某个功能时,有人请你审查一个 PR:
|
|
当你审查完毕:
|
|
删除。干净利落。不会意外地将审查更改提交到你的功能分支。
注意:
tree-me使用 gh CLI 来获取 PR。如果你没有安装它,可以使用brew install gh安装。
安装
下载 tree-me 并将其放在你的 PATH 路径中的某个位置:
|
|
然后启用自动 cd 和选项卡补全(参见上面的设置部分)。
就这样。除了 git、bash 以及用于 PR 检出的 gh CLI(可选)之外,没有其他依赖项。
我为什么要构建这个工具
我每天处理多个仓库——PostHog、我的博客、各种开源项目。我厌倦了记住项目特定的工作树脚本,以及寻找上周创建的那个工作树。
理念是: 不要重新造轮子去做 Git 已经做得很好的事情。只添加最少的必要约定。
Git 本身已经完美地处理了工作树。我只需要有组织的路径、合理的默认值以及跨所有项目的一致接口。
目录结构
所有内容都基于仓库名称和分支名称进行可预测的组织:
|
|
例如:
|
|
一眼就知道所有东西在哪里。
它不做的事情
tree-me 不复制环境文件、不安装依赖项、不设置项目特定的工具。这是有意为之的。这些问题应该放在你的项目设置脚本中,而不是放在一个通用的 Git 工具里。
想要自动化环境设置?在你的仓库中添加一个在检出后运行的脚本。想要复制 .env 文件?把它放在你的项目入门文档中。tree-me 只处理 Git 工作树相关的繁琐操作。
试试看
如果你经常处理多个分支,请尝试一下工作树。如果你处理多个仓库,请尝试一下 tree-me。如果你不喜欢它,至少你了解了 Git 工作树(这可能比脚本本身更有价值)。
在 github.com/haacked/dotfiles/blob/main/bin/tree-me 找到 tree-me。它是 MIT 许可证的——复制、修改、改进它。