Skip to content

Latest commit

 

History

History
155 lines (110 loc) · 5.23 KB

File metadata and controls

155 lines (110 loc) · 5.23 KB

Git Worktree 如何工作

一句话理解

一个仓库(.git)可以挂多个工作目录:每个目录各自检出不同分支,共享同一份对象库与历史,互不影响对方的未提交改动。

为什么需要它

传统用法里,一个 clone 同一时间只能 checkout 一个分支。要并行改两个分支,通常只能再 clone 一份,代价是:

  • 重复下载、重复占用磁盘上的对象
  • 两个 clone 的配置、hooks、reflog 容易漂移

git worktree 解决的是:同一仓库,多份检出。适合:

  • 主线继续开发,另开目录修 hotfix
  • 一边跑长构建/测试,一边在别的分支改代码
  • AI Agent / IDE 在隔离目录里并行实验,不弄脏主工作区

核心模型

repository(一份 .git)
├── main worktree      ← clone / init 时的那个目录
│   ├── HEAD → branch A
│   ├── index
│   └── 工作区文件
└── linked worktrees   ← git worktree add 加出来的
    ├── /path/to/wt-b  → branch B
    └── /path/to/wt-c  → branch C(或 detached HEAD)
概念 含义
Main worktree git clone / git init 得到的主工作树
Linked worktree git worktree add 挂上的额外工作树
共享 commits、blobs、refs、config(仓库级)
不共享 每个 worktree 自己的 HEAD、index、未跟踪文件、部分 per-worktree 配置

约束:同一个分支不能同时被两个 worktree 检出(避免两个目录改同一分支、提交互相踩踏)。需要并行时,给新 worktree 建新分支,或用 --detach

磁盘上实际长什么样

主仓库里会多出管理信息,大致在:

.git/worktrees/<id>/
  ├── HEAD          # 该 worktree 当前指向
  ├── gitdir        # 指向该工作目录里的 .git 文件
  ├── locked        # 若被 lock
  └── ...

Linked worktree 目录里通常不是完整 .git 文件夹,而是一个文件,内容类似:

gitdir: /path/to/main-repo/.git/worktrees/<id>

所以删目录时若不走 git worktree remove,主仓库里可能留下过期的管理条目,需要 prune 清理。

常用命令

查看

git worktree list
git worktree list -v

新增

# 在 path 创建新分支(分支名默认取 path 最后一段)并检出
git worktree add ../hotfix

# 检出已有分支到新目录
git worktree add ../feature-foo feature-foo

# 显式建新分支再检出
git worktree add -b experiment ../experiment main

# 临时实验:detached HEAD,不绑分支
git worktree add --detach ../scratch

移动 / 删除 / 清理

git worktree move <worktree> <new-path>
git worktree remove <worktree>
git worktree remove -f <worktree>   # 有未提交改动时强制

# 工作目录已被手动删掉时,清掉残留元数据
git worktree prune

锁定(可选设备 / 网络盘)

工作树在外置盘或不常挂载的路径上时,可 lock,避免被自动 prune:

git worktree lock ../portable-wt --reason "on USB drive"
git worktree unlock ../portable-wt

典型工作流

# 当前在 main 上开发
cd ~/proj

# 紧急修复:另开目录,从 main 拉 hotfix 分支
git worktree add -b hotfix/login ../proj-hotfix main
cd ../proj-hotfix
# ... 修、测、提交、推送 ...
git push -u origin hotfix/login

# 用完后回到主目录清理
cd ~/proj
git worktree remove ../proj-hotfix

主目录里的未提交改动不受影响;hotfix 目录有自己的 index 与工作区。

和「再 clone 一份」的对比

再 clone worktree
对象库 各一份(或靠引用复制仍偏重) 共享一份
分支可见性 需分别 fetch 同一仓库,立刻可见
并行检出不同分支 可以 可以
清理 删整个目录 remove + 必要时 prune
适用 完全隔离的机器/权限边界 本机并行开发、临时实验

注意点

  1. 分支独占branch X 已在某个 worktree,就不能再 add 检出到另一个;用 -b 新分支或 --detach
  2. 删目录要用命令:直接 rm -rf 工作目录后,记得 git worktree prune
  3. 子模块 / 依赖:每个 worktree 是独立工作区;node_modules 等通常各自安装,不共享。
  4. bare 仓库:可以只有 linked worktrees、没有「带工作区的 main」;常见于集中管理多检出的布局。
  5. Cursor / Agent:隔离实验目录时,worktree 比改同一工作区再 stash 更干净——主目录继续用,实验目录随时丢弃。

最小心智模型

Worktree = 共享历史的额外 checkout
改的是「当前这个目录的分支与文件」;提交仍进同一个仓库。用完 remove,别只删文件夹。

延伸阅读