在日常开发中,我们经常需要在多个分支之间切换,比如正在开发一个新功能时,突然需要修复线上问题。传统的做法是使用 git checkout 切换分支,但这会中断当前的工作进度。
有没有办法让我们在不切换分支的前提下,同时编辑多个分支呢?答案是肯定的 —— Git Worktree 正是为此而生!
官方文档参考:Git - git-worktree Documentation
1. 什么是 Git Worktree?
Git Worktree 是 Git 提供的一个功能,允许你在同一个仓库中拥有多个工作树(working tree),每个工作树可以检出不同的分支,并且彼此独立操作。
这意味着你可以:
- 同时开发 main 和 feature 分支;
- 在不提交当前修改的情况下切换到其他分支进行紧急修复;
- 并行运行不同分支以测试其行为差异;
- 构建与部署不同环境(dev/staging/prod)版本。
2. 官方命令一览
以下是 Git Worktree 支持的完整命令列表:
git worktree add [-f] [--detach] [--checkout] [--lock [--reason <string>]]
[--orphan] [(-b | -B) <new-branch>] <path> [<commit-ish>]
git worktree list [-v | --porcelain [-z]]
git worktree lock [--reason <string>] <worktree>
git worktree move <worktree> <new-path>
git worktree prune [-n] [-v] [--expire <expire>]
git worktree remove [-f] <worktree>
git worktree repair [<path>…]
git worktree unlock <worktree>
3. 各命令详解与使用示例
3.1 git worktree add:创建工作树
这是最常用的命令之一,用于添加一个新的工作树。
基本语法:
git worktree add [-f] [--detach] [--checkout] [--lock [--reason <string>]]
[--orphan] [(-b | -B) <new-branch>] <path> [<commit-ish>]
参数说明:
参数 |
含义 |
-f |
强制添加,即使目标路径已存在(但必须为空) |
--detach |
创建分离头指针状态的工作树 |
--checkout |
自动检出指定提交(默认行为) |
--lock |
锁定该工作树防止误删 |
--reason |
配合 --lock 使用,说明锁定原因 |
-b <branch> |
创建新分支并关联到当前工作树 |
-B <branch> |
创建或重置一个分支 |
<path> |
新工作树的路径 |
<commit-ish> |
可选,要检出的提交(如分支名、tag、commit hash) |
示例:
# 创建新分支 feature/login 并关联到 ../login-worktree 路径
git worktree add -b feature/login ../login-worktree
# 添加已有 dev 分支到新的目录
git worktree add ../dev dev
# 强制添加到已存在的空目录
git worktree add -f ../existing-dir dev
# 创建并锁定工作树防止误删
git worktree add --lock ../locked-worktree dev
3.2 git worktree list:查看所有工作树
列出当前仓库下的所有工作树及其状态。
基本语法:
git worktree list
常用参数:
参数 |
含义 |
-v |
显示详细信息 |
--porcelain |
输出机器可读格式 |
-z |
与 --porcelain 搭配使用,使用 NUL 字符分隔每条记录 |
示例:
# 查看当前所有工作树
git worktree list
# 输出机器可读格式(适合脚本解析)
git worktree list --porcelain
# 支持含换行符路径的解析
git worktree list --porcelain -z
注意(来自 Git Worktree 机器可读输出规范):
- --porcelain 格式稳定,适用于脚本处理。
- -z 参数确保即使路径中包含换行符也能被正确识别。
- 推荐组合使用 --porcelain -z 进行自动化处理。
3.3 git worktree lock:锁定已有工作树
用于对已经存在的工作树进行锁定,防止被误删。
基本语法:
git worktree lock [--reason <string>] <worktree>
示例:
git worktree lock --reason "保护 hotfix 分支" ../hotfix
3.4 git worktree unlock:解锁工作树
用于解锁之前被锁定的工作树。
基本语法:
git worktree unlock <worktree>
示例:
git worktree unlock ../hotfix
3.5 git worktree remove:删除工作树
移除某个工作树记录,不会影响对应的分支(除非使用 -f)。
基本语法:
git worktree remove [-f] <worktree>
示例:
# 删除工作树但保留分支
git worktree remove ../feature-login
# 彻底删除工作树及对应分支
git worktree remove -f ../feature-login
3.6 git worktree move:移动工作树路径
用于更改已有工作树的路径,适用于你需要重新组织项目结构时。
基本语法:
git worktree move <worktree> <new-path>
示例:
git worktree move ../feature-login ../feature-auth
3.7 git worktree prune:清理无效工作树记录
清理那些指向不存在路径的工作树记录。
基本语法:
git worktree prune [-n] [-v] [--expire <expire>]
常用参数:
参数 |
含义 |
-n, --dry-run |
模拟执行,仅显示哪些工作树会被清理,不真正删除任何记录 |
-v, --verbose |
显示详细操作信息,例如哪些工作树被跳过、哪些被清理 |
--expire <time> |
清理超过指定时间未使用的“可修剪”工作树(如 3.days.ago)。如果不设置,默认立即清理所有可修剪的工作树 |
示例:
# 查看可修剪的工作树
git worktree list --prune
# 执行清理
git worktree prune
# 清理超过三天未使用的记录
git worktree prune --expire 3.days.ago
关于 --expire <time> 说明:
在Git中,日期可以以多种格式输入。下面介绍几种常用的日期输入格式。
1. 标准日期格式:yyyy-mm-dd
例如:”2022-09-30″ 表示2022年9月30日。
2. 相对日期格式:
- 现在:now
- 一秒前:1.second.ago(或 1.seconds.ago)
- 一分钟前:1.minute.ago(或 1.seconds.ago)
- 一小时前:1.hour.ago(或 1.hours.ago)
- 昨天:yesterday
- 前天:2.day.ago (或 1.days.ago)
- 前一周:1.week.ago(或 1.weeks.ago)
- 前一个月:1.month.ago(或 1.months.ago)
- 前一年:1.year.ago(或 1.years.ago)
3. 相对于当前日期的偏移量格式:+/-
其中, 表示时间数量, 表示时间单位。
- 一个月之后(相对于当前日期):+1 month
- 一周之前(相对于当前日期):-1 week
- 两天之后(相对于当前日期):+2 days
4. 绝对日期格式:yyyy-mm-dd HH:MM:SS
在标准日期格式的基础上加上具体的时间,表示某个特定的时间点。
例如:”2022-09-30 10:30:00″ 表示2022年9月30日上午10点30分。
3.8 git worktree repair:修复损坏的工作树链接
修复因外部操作导致损坏或过期的工作树元数据文件(如 .git/worktrees/<name>/ 中的路径记录)。
适用场景:
- 主工作树(main worktree)或裸仓库(bare repo)被手动移动;
- 链接工作树(linked worktree)被手动移动但未使用 git worktree move;
- 多个工作树被复制或移动后路径异常;
- Git 记录的路径与实际路径不一致。
工作原理详解:
Git Worktree 使用 .git/worktrees/ 目录来保存每个工作树的元数据信息,包括路径、HEAD 指针等。
当这些路径由于外部操作(如手动移动目录、复制仓库结构等)发生变化时,Git 将无法正确识别这些工作树,表现为:
- git worktree list 显示路径错误;
- 无法执行 git worktree remove 或 prune;
- 出现“worktree path does not exist”等错误。
基本语法:
git worktree repair [<path>...]
示例:
git worktree repair ../feature-login ../hotfix
双向修复机制说明:
场景 |
如何修复 |
主工作树被移动 |
在主工作树目录下运行 git worktree repair,Git 会自动更新所有链接工作树对其路径的引用 |
链接工作树被移动 |
在任意工作树中运行 git worktree repair <moved-path>,Git 会更新主工作树中对该路径的引用 |
多个链接工作树被移动 |
在任意工作树中运行 git worktree repair <path1> <path2> ...,Git 会批量修复 |
主工作树和多个链接工作树都被移动 |
在新的主工作树目录中运行 git worktree repair <new-linked-path1> <new-linked-path2>...,Git 会双向修复所有路径 |
注意事项:
- 不要直接修改 .git/worktrees/ 目录下的内容;
- 手动移动工作树后务必运行 repair;
- 推荐优先使用 git worktree move 进行路径变更;
- 定期运行 git worktree prune,清理无效记录,保持环境整洁。
4. 典型使用场景
4.1 并行开发多个功能分支
# 主工作树保持在 main 分支
cd D:/project
# 新建两个功能分支工作树
git worktree add ../feature-a feature-a
git worktree add ../feature-b feature-b
你可以在不同终端窗口分别进入 ../feature-a 和 ../feature-b 目录独立开发、提交、调试。
4.2 快速修复线上问题
# 当前在 feature 分支上开发
cd D:/project
# 创建 hotfix 分支用于紧急修复
git worktree add -b hotfix ../hotfix main
# 进入 hotfix 工作树进行修复
cd ../hotfix
git commit -am "Fix critical bug"
git push origin hotfix
完成后主分支仍可继续开发,互不影响。
4.3 锁定关键工作树防止误删
# 创建并锁定工作树
git worktree add --lock ../prod-release main
# 或者单独锁定已有工作树
git worktree lock --reason "生产环境分支" ../prod-release
尝试删除时会被阻止:
git worktree remove ../prod-release
error: 'D:/project/prod-release' is locked
4.4 脚本解析支持(来自 Git Worktree 机器可读输出规范)
示例:结合 --porcelain 和 -z 的 Bash 脚本
# Bash 脚本解析工作树信息
while IFS= read -r -d '' line; do
echo "Line: $line"
done < <(git worktree list --porcelain -z)
这段脚本可以安全地遍历所有工作树,即使路径中包含换行符也能正确识别。
5. 总结
Git Worktree 是一个非常强大的工具,它允许你在同一仓库内管理多个工作树,极大地提升了多分支开发效率。通过合理使用它可以:
- 减少频繁切换分支;
- 避免打断当前开发思路;
- 快速切换上下文进行紧急修复;
- 支持并行构建、测试、部署多个版本;
- 结合脚本实现自动化运维和清理。