SuperAPI AI 工具集

git-worktree

编程与开发

查看项目

更新于 10-15 10:59

技能介绍

用途

git worktree 是 Git 提供的一项功能,用于在同一个仓库上创建额外的工作目录。每个仓库初始只有一个工作树(主工作树),通过 git worktree add 可以添加链接工作树。所有工作树共享同一个 .git 对象库、引用(分支、标签)、配置、钩子、远程跟踪信息和 rerere 缓存;但每个工作树拥有独立的工作区文件、索引(暂存区)、HEAD、MERGE_HEAD、REBASE_HEAD、CHERRY_PICK_HEAD、.env 文件、node_modules 和构建产物。

主工作树由 git init 或 git clone 创建,无法通过 git worktree remove 删除;链接工作树可以自由添加和删除。内部实现上,每个链接工作树在 .git/worktrees/<name>/ 下拥有自己的 HEAD、索引和跟踪文件,其工作目录中的 .git 是一个指向该位置的文本文件而非目录。

主要能力

  • 从已有分支创建工作树:git worktree add ../hotfix-login hotfix/login
  • 从新分支创建工作树:git worktree add -b feature/search ../feature-search main
  • 从特定提交创建(分离 HEAD):git worktree add --detach ../investigate-crash abc1234
  • 从远程分支创建:先 git fetch origin,再 git worktree add ../review-pr42 origin/pr-42
  • 列出工作树:git worktree list(加 --porcelain 输出机器可读格式)
  • 移除工作树:git worktree remove ../hotfix-login(--force 可丢弃未提交更改)
  • 移动工作树:git worktree move ../hotfix-login ../hotfix-auth
  • 锁定/解锁:git worktree lock ../usb-worktree --reason "on external drive" 与 git worktree unlock ../usb-worktree
  • 清理失效条目:git worktree prune(可先 --dry-run 预览)

使用方式

与 stash、分支切换、克隆相比,worktree 适合并行工作并保持多个上下文存活。stash 适合 5 分钟内的快速中断,但会导致线性工作流和 stash 堆积;分支切换要求工作区干净;克隆则完全隔离但会复制对象库。worktree 共享对象库,在 2 GB 历史的仓库上,第二个工作树仅占用工作区文件大小,而第二个克隆需要 2 GB 加工作区。分支和标签在所有工作树间即时更新,钩子和配置也共享。

目录布局推荐同级目录(如 ~/projects/myapp、myapp-hotfix、myapp-review)或子目录布局配合裸仓库模式。裸仓库模式通过 git clone --bare 创建无默认工作树的仓库,再为各分支创建工作树,避免默认分支已被检出的问题。

常见工作流包括:功能开发中途紧急热修复、工作区脏时审查 PR、一个分支编码另一个分支跑测试、并排比较不同分支行为。每个工作树有独立的 node_modules、dist、build、.env 和生成文件,需要独立运行安装命令;构建缓存不共享。子模块不会自动初始化,需在每个新工作树中运行 git submodule update --init --recursive。

CI/CD 中可在单个任务内测试多个分支,无需多次克隆。IDE 方面,VS Code 用 code ../myapp-hotfix 打开新窗口,JetBrains 通过 File > Open 打开工作树目录,Vim/Neovim 直接 cd 进入即可,任何能打开文件夹的编辑器都无需特殊配置。

适用场景

  • 并行开发多个分支,保持各自未提交的上下文
  • 生产环境故障时快速创建热修复工作树
  • 审查 PR 而不影响当前进行中的工作
  • 在一个分支编码的同时在另一个工作树运行测试
  • 并排运行不同分支的应用进行行为对比
  • CI 中并行测试多个分支,节省时间和磁盘
  • 裸仓库配合工作树管理多个分支的检出
  • dotfiles 管理

限制

  • 同一分支不能在两个工作树中同时检出,Git 会阻止;可用 --detach 或临时分支绕过
  • 每个工作树需要独立安装依赖,构建缓存不共享
  • 直接删除目录而不使用 git worktree remove 会留下孤立条目,需用 git worktree prune 清理
  • git gc 影响所有工作树,激进修剪可能移除其他工作树索引仍引用的对象
  • git config 默认写入共享配置,需启用 extensions.worktreeConfig 后使用 git config --worktree 实现每工作树配置
  • 主工作树无法移动或移除
  • 工作树不自动初始化子模块
  • 额外磁盘空间占用(工作区文件)