Git Worktree 高效管理利器:tree-me 工具详解

本文深入介绍了 Git 的 worktree 功能以及一个名为 tree-me 的便捷工具。tree-me 通过封装 Git 原生命令,简化了多分支并行开发的工作流,支持自动路径组织、PR 拉取和自动跳转,旨在提升开发效率。

我坚信 Git 工作树是 Git 中最被低估的功能之一。我多年来一直忽略它们,因为我不理解它们,也不知道如何将其融入我的工作流程。

但随着我开始使用 LLM 编码工具进行更多的并行工作,这种情况发生了改变。能够同时处理多个分支是一个巨大的变革。

没有 Git 工作树,在同一个仓库中同时处理多个分支是一件很痛苦的事。要么采用串行方式:暂存你的更改,切换上下文,然后祈祷没有搞坏任何东西。或者更糟的是,直接用“WIP”消息提交未完成的工作(看着你呢,过去的我)。或者,你可以拥有同一个仓库的多个克隆,但这管理起来很麻烦,并且会占用大量磁盘空间。

Git 工作树解决了这个问题。它们允许你在不同的目录中同时检出多个分支,所有这些目录都共享同一个 Git 数据库(即 .git 目录)。对我来说,这意味着我可以在一个终端中处理一个功能,在另一个终端中审查 PR,让 Claude Code 在另一个终端中处理另一个功能,并且所有这些工作都共享相同的 Git 历史记录。

但问题是:手动创建工作树很繁琐。你需要记住把它们放在哪里,如何命名,以及之后清理它们。此外,默认情况下,除非你指定其他目录,否则 Git 工作树会在仓库的根目录中创建。

我想要一些更简单的东西。我想要一个在任何仓库中都能工作的东西。无需设置,没有配置文件,只有合理的默认值。

欢迎使用 tree-me

我构建了 tree-me,这是一个对 Git 原生工作树命令的最小化封装。它在让 Git 处理所有复杂性的同时,增加了组织性规范。

你可以不用这样:

1
2
3
4
5
# 手动创建工作树
mkdir -p ~/worktrees/my-project
git worktree add ~/worktrees/my-project/fix-bug -b haacked/fix-bug main
cd ~/worktrees/my-project/fix-bug
# 对每个仓库重复此操作...

而是这样做:

1
2
3
tree-me create haacked/fix-bug
# 创建:~/dev/worktrees/my-project/haacked/fix-bug
# 并自动 cd 进入该目录

工作原理

tree-me 使用类似 Git 的子命令并遵循约定,因此您无需思考:

  • 根据 Git 远程仓库自动检测仓库名称
  • 自动检测默认分支(检查 origin/HEAD,回退到 main)
  • 按仓库组织:$WORKTREE_ROOT/<repo-name>/<branch-name>
  • 将所有验证、错误和边缘情况委托给 Git 处理
  • PR 支持:使用 Git 的原生 PR 引用获取 GitHub PR(需要 gh CLI)
  • 自动 CD:创建后自动切换到工作树目录
  • 选项卡补全:在 bash/zsh 中补全命令和分支名称

命令:

1
2
3
4
5
6
7
tree-me create <branch> [base]        # 在工作树中创建新分支
tree-me checkout <branch>             # 检出现有分支(别名:co)
tree-me pr <number|url>               # 检出 GitHub PR(使用 gh CLI)
tree-me list                          # 列出所有工作树(别名:ls)
tree-me remove <branch>               # 删除工作树(别名:rm)
tree-me prune                         # 清理过时的工作树文件
tree-me shellenv                      # 输出用于自动 cd 的 shell 函数

示例:

1
2
3
4
5
6
7
tree-me create haacked/fix-bug              # 从 main/master 创建
tree-me create haacked/fix-bug develop      # 从 develop 创建
tree-me co existing-feature                 # 检出现有分支
tree-me pr 123                              # 检出 PR #123
tree-me pr https://github.com/org/repo/pull/456
tree-me ls                                  # 显示所有工作树
tree-me rm haacked/fix-bug                  # 清理(支持选项卡补全)

约定

tree-me 是 Git 原生命令的最小化封装。适用于任何仓库、任何语言、任何设置。唯一的约定是工作树的存放位置和命名方式。

希望工作树放在不同的位置?设置 WORKTREE_ROOT 环境变量。需要从 develop 而不是 main 创建分支?将其作为参数传递:tree-me create my-feature develop。这是一个有逃生舱口的约定。

设置

要启用自动 cd 和选项卡补全,请将以下内容添加到您的 ~/.bashrc~/.zshrc 中:

1
source <(tree-me shellenv)

这使得 tree-me createtree-me checkouttree-me pr 能够自动 cd 到工作树目录。它还为命令和分支名称启用了选项卡补全(试试 tree-me rm <TAB>)。

完整实现请查看 github.com/haacked/dotfiles/blob/main/bin/tree-me

PR 审查工作流

这是它大放异彩的地方。当你正深入开发某个功能时,有人请你审查一个 PR:

1
2
3
4
5
6
tree-me pr 123                  # 获取、检出 PR 并 cd 进入
# 你现在位于:~/dev/worktrees/dotfiles/pr-123
# 审查代码,测试它,留下评论
# 完成后,切换回去
tree-me co haacked/my-feature   # 检出并 cd 回你的功能分支
# 回到你的工作,无需暂存

当你审查完毕:

1
tree-me rm pr-123               # 按 Tab 补全查看可用分支

删除。干净利落。不会意外地将审查更改提交到你的功能分支。

注意:tree-me 使用 gh CLI 来获取 PR。如果你没有安装它,可以使用 brew install gh 安装。

安装

下载 tree-me 并将其放在你的 PATH 路径中的某个位置:

1
2
3
# 示例:复制到 ~/bin 或 ~/.local/bin
curl -o ~/bin/tree-me https://raw.githubusercontent.com/haacked/dotfiles/main/bin/tree-me
chmod +x ~/bin/tree-me

然后启用自动 cd 和选项卡补全(参见上面的设置部分)。

就这样。除了 git、bash 以及用于 PR 检出的 gh CLI(可选)之外,没有其他依赖项。

我为什么要构建这个工具

我每天处理多个仓库——PostHog、我的博客、各种开源项目。我厌倦了记住项目特定的工作树脚本,以及寻找上周创建的那个工作树。

理念是: 不要重新造轮子去做 Git 已经做得很好的事情。只添加最少的必要约定。

Git 本身已经完美地处理了工作树。我只需要有组织的路径、合理的默认值以及跨所有项目的一致接口。

目录结构

所有内容都基于仓库名称和分支名称进行可预测的组织:

1
~/dev/worktrees/<repo-name>/<branch-name>

例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
~/dev/worktrees/
├── dotfiles/
   ├── haacked/vim-improvements/
   ├── haacked/git-tools/
   └── main/
├── posthog/
   ├── haacked/feature-flags/
   ├── pr-789-contributor/
   └── main/
└── spelungit/
    └── haacked/performance/

一眼就知道所有东西在哪里。

它不做的事情

tree-me 不复制环境文件、不安装依赖项、不设置项目特定的工具。这是有意为之的。这些问题应该放在你的项目设置脚本中,而不是放在一个通用的 Git 工具里。

想要自动化环境设置?在你的仓库中添加一个在检出后运行的脚本。想要复制 .env 文件?把它放在你的项目入门文档中。tree-me 只处理 Git 工作树相关的繁琐操作。

试试看

如果你经常处理多个分支,请尝试一下工作树。如果你处理多个仓库,请尝试一下 tree-me。如果你不喜欢它,至少你了解了 Git 工作树(这可能比脚本本身更有价值)。

github.com/haacked/dotfiles/blob/main/bin/tree-me 找到 tree-me。它是 MIT 许可证的——复制、修改、改进它。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计