1. 什么是 git worktree? #
- git worktree 让你在同一台电脑上,把同一个 Git 仓库的多个分支同时检出到不同文件夹里。
- 平时一个仓库只有一个工作目录:
git switch 换分支时,当前文件夹里的文件会跟着变。
- 有了 worktree,每个分支可以占用一个独立文件夹,互不干扰,不必先
stash 再切换。
- 口诀:一个仓库,多个目录,同时工作,不必切换。
2. 前置知识 #
- 使用 worktree 前,先弄清下面三个概念,否则容易和「再 clone 一份」搞混。
2.1 仓库、工作目录、分支 #
- 仓库(repository):保存提交历史的地方,核心在
.git 目录里。
- 工作目录(working tree):你平时打开、编辑文件的那个文件夹。
- 分支(branch):指向某一条提交历史的名字,如
main、feature/login。
- 默认情况:一个仓库只有一份工作目录,同一时间只能检出一个分支。
2.2 普通切换分支 vs worktree #
- 普通切换:在同一个文件夹里换分支,未提交改动可能挡住切换,常要用
git stash。
- worktree:再开一个新文件夹,检出另一个分支;原文件夹里的未完成改动原样保留。
- 两者都用同一个
.git 对象库,不是再下载一遍完整历史。
2.3 主工作树与两个概念 #
- 主工作树:你最初
git clone 或 git init 所在的那个目录。
- 附加工作树(linked worktree):用
git worktree add 新建出来的目录。
- 附加工作树里通常没有完整
.git 文件夹,而是一个指向主仓库的小文件,历史与主仓库共享。
3. 为什么需要 worktree? #
- 下面三个场景,最能体现 worktree 的价值。
3.1 功能做到一半,突然要修 bug #
- 你在
feature 分支改到一半,还不能提交。
- 线上出紧急问题,需要基于
main 马上修。
- 传统做法:
stash → 切 main → 修完 → 切回 → stash pop,容易乱、容易冲突。
- worktree 做法:另开一个目录专门修 bug,原功能目录一行代码都不用动。
3.2 需要同时看两个分支的代码 #
- 想对照
feature-a 和 feature-b 的差异时,只有一个目录就要来回切。
- 用 worktree 开两个目录,编辑器可以左右对比,或同时运行两个本地服务。
3.3 和「再 clone 一次」比有什么好处? #
- 再 clone:又下载一份完整历史,占空间、占时间。
- worktree:工作文件各有一份,提交历史共享,省磁盘、创建也快。
4. 环境准备 #
- worktree 是 Git 自带命令,无需额外安装软件。
- Windows 上请确认已安装 Git,并能在 CMD 终端里执行命令。
- Git 2.5+ 即可使用;日常建议 2.30+。
4.1 检查 Git 版本 #
:: 说明:查看当前安装的 Git 版本号
git --version
4.2 一键创建仓库 #
- 下面脚本会在当前目录下创建
wt-repo 仓库,并做好第一次提交。
- 可独立运行;已经存在同名目录时请先删掉或换个目录执行。
:: 说明:若已存在演示目录则先删除,保证可重复运行
if exist wt-repo rd /s /q wt-repo
:: 说明:新建仓库目录
md wt-repo
:: 说明:进入仓库
cd wt-repo
:: 说明:初始化 Git 仓库(默认分支名设为 main)
git init -b main
:: 说明:配置本仓库专用的用户名(仅影响当前仓库)
git config user.name "Worktree"
:: 说明:配置本仓库专用的邮箱
git config user.email "Worktree@example.com"
:: 说明:写入一个示例文件
echo hello worktree> README.md
:: 说明:把文件加入暂存区
git add README.md
:: 说明:创建第一次提交
git commit -m "init: repo"
:: 说明:打印当前目录与当前分支,确认创建成功
cd
git branch --show-current
5. 核心概念 #
5.1 每个分支同一时刻只能在一个工作树里 #
- 若
main 已经在主目录检出,就不能再给另一个目录也检出 main。
- 做法:给修 bug 的目录新建一个分支(如
hotfix/urgent),基于 main 创建。
5.2 新目录建议放在主仓库旁边 #
- 不要把工作树目录建在主仓库内部(容易混乱)。
- 推荐布局:
项目-main 与 项目-hotfix 同级,例如:
D:\code\wt-repo(主仓库)
D:\code\wt-repo-hotfix(附加工作树)
5.3 删目录不等于彻底清理 #
- 手动删掉工作树文件夹后,Git 里可能还留着记录。
- 应用
git worktree remove 规范删除,或删除后执行 git worktree prune。
6. 常用命令 #
- 日常只需要会:list(查看)→ add(添加)→ remove(移除)。
- 以下命令默认在主仓库目录里执行。
6.1 查看所有工作树 #
git worktree list 会列出每个工作目录路径、当前提交、检出的分支。
:: 说明:进入仓库(若你已在该目录可省略)
cd wt-repo
:: 说明:列出当前仓库关联的全部工作树
git worktree list
6.2 添加工作树(检出已有分支) #
- 先有一个分支,再为它单独开一个目录时,用这种写法。
- 下面示例会新建
feature/notes 分支,再把它放到旁边的目录。
:: 说明:进入主仓库
cd wt-repo
:: 说明:从当前 HEAD 创建分支 feature/notes(还不打开新工作树)
git branch feature/notes
:: 说明:把 feature/notes 检出到上一级目录的 wt-repo-notes 文件夹
git worktree add ..\wt-repo-notes feature/notes
:: 说明:再次列出工作树,应看到两行
git worktree list
6.3 添加工作树(同时新建分支) #
- 最常用:一边开新目录,一边基于某个起点建新分支。
-b 表示「创建新分支」;最后的 main 表示「以 main 为起点」。
:: 说明:进入主仓库
cd wt-repo
:: 说明:基于 main 新建 hotfix/urgent,并检出到旁边的 wt-repo-hotfix
git worktree add -b hotfix/urgent ..\wt-repo-hotfix main
:: 说明:进入新工作树看当前分支
cd ..\wt-repo-hotfix
git branch --show-current
:: 说明:回到主仓库(主仓库仍保持原来的状态)
cd ..\wt-repo
git branch --show-current
6.4 移除工作树 #
- 先离开那个目录,再在主仓库中执行
git worktree remove。
- 若目录里有未提交修改,Git 会拒绝删除;确认不需要后可用
--force(慎用)。
:: 说明:确保当前不在即将删除的工作树里,回到主仓库
cd wt-repo
:: 说明:移除 notes 工作树(会删除对应目录)
git worktree remove ..\wt-repo-notes
:: 说明:移除 hotfix 工作树
git worktree remove ..\wt-repo-hotfix
:: 说明:查看结果,应只剩主工作树
git worktree list
6.5 手动删目录后的清理 #
- 若用资源管理器直接删了工作树文件夹,可用
prune 清理失效记录。
:: 说明:进入主仓库
cd wt-repo
:: 说明:清理已不存在目录的残留 worktree 记录
git worktree prune
:: 说明:再次查看列表确认
git worktree list
7. 实战:功能做到一半,紧急修 bug #
- 这是 worktree 最经典的用法。
- 下面脚本演示:主仓库有未提交改动,同时在新目录修 bug 并提交。
:: 说明:清理上次演示留下的目录
if exist wt-repo rd /s /q wt-repo
if exist wt-repo-hotfix rd /s /q wt-repo-hotfix
:: 说明:创建并进入主仓库
md wt-repo
cd wt-repo
git init -b main
git config user.name "Worktree Demo"
git config user.email "demo@example.com"
echo version on main> README.md
git add README.md
git commit -m "init: main"
:: 说明:模拟你在写功能:新建 feature 分支并留下未提交修改
git switch -c feature/login
echo WIP: login form half done> feature.txt
:: 说明:此时有未提交文件,但我们不去 stash,而是另开 hotfix 工作树
git status --short
:: 说明:基于 main 开 hotfix 工作树(不碰主仓库未完成改动)
git worktree add -b hotfix/urgent ..\wt-repo-hotfix main
:: 说明:进入 hotfix 目录,修复一个假 bug
cd ..\wt-repo-hotfix
echo version on main - bug fixed> README.md
git add README.md
git commit -m "fix: critical bug on main"
:: 说明:打印 hotfix 提交结果
echo hotfix 最新提交:
git log -1 --oneline
:: 说明:回到 feature 目录,未完成改动仍然在
cd ..\wt-repo
echo 主仓库仍有未提交文件:
git status --short
echo 当前分支:
git branch --show-current
:: 说明:清理本次演示
git worktree remove ..\wt-repo-hotfix
cd ..
rd /s /q wt-repo
echo 演示完成并已清理
8. 实战:同时查看两个分支 #
- 场景:
main 与 feature/ui 各放一个目录,方便对比文件。
- 可独立运行。请在 CMD 中执行。
:: 说明:清理旧演示目录
if exist wt-repo rd /s /q wt-repo
if exist wt-repo-ui rd /s /q wt-repo-ui
:: 说明:创建主仓库并提交初始内容
md wt-repo
cd wt-repo
git init -b main
git config user.name "Worktree Demo"
git config user.email "demo@example.com"
echo console.log('main');> app.js
git add app.js
git commit -m "init: main app"
:: 说明:创建 feature/ui 分支并改文件,再切回 main
git switch -c feature/ui
echo console.log('feature ui');> app.js
git add app.js
git commit -m "feat: ui branch change"
git switch main
:: 说明:把 feature/ui 放到旁边目录,主目录保持 main
git worktree add ..\wt-repo-ui feature/ui
:: 说明:对比两个目录中同一文件的内容
echo ===== main 目录 app.js =====
type app.js
echo ===== ui 工作树 app.js =====
type ..\wt-repo-ui\app.js
:: 说明:用 git 看两个分支差异(在主仓库执行即可)
git diff main..feature/ui
:: 说明:清理
git worktree remove ..\wt-repo-ui
cd ..
rd /s /q wt-repo
echo 演示完成并已清理
9. 常见问题 #
9.1 提示分支已被检出(already checked out) #
- 原因:该分支已经在另一个工作树里使用。
- 解决:换一个新分支名(
git worktree add -b 新分支名 路径 起点),或先移除占用该分支的工作树。
9.2 remove 失败,提示有未提交修改 #
- 原因:目标工作树里还有改动,Git 默认保护你。
- 解决:先进去提交或丢弃改动;确认不要了再用
git worktree remove --force 路径。
9.3 list 里还能看到已删除的目录 #
- 原因:用资源管理器删了文件夹,记录没同步。
- 解决:在主仓库执行
git worktree prune。
9.4 主仓库还能看到 hotfix 分支吗? #
- 能。worktree 共享一套分支。
- 修完 bug 后,可在主仓库合并:
git merge hotfix/urgent,再按需要删除分支。
- 删除分支前,请先
remove 掉正在检出该分支的工作树。
10. 命令速查 #
| 操作 |
命令 |
| 进入目录 |
cd wt-repo |
| 新建目录 |
md wt-repo |
| 删除目录 |
rd /s /q wt-repo |
| 查看工作树 |
git worktree list |
| 基于现有分支新建目录 |
git worktree add ..\项目-notes feature/notes |
| 新建分支并打开目录 |
git worktree add -b hotfix/urgent ..\项目-hotfix main |
| 移除工作树 |
git worktree remove ..\项目-hotfix |
| 强制移除 |
git worktree remove --force ..\项目-hotfix |
| 清理失效记录 |
git worktree prune |
- 推荐工作流:主目录做日常功能 → 紧急问题另开 hotfix 目录 → 修完提交 → remove 掉工作树 → 回主仓库合并。
- 记住限制:同一分支不要同时在两个目录检出;新目录放在主仓库旁边,不要嵌套在内部。