用 git worktree 同时打开两个分支

摘要

  • 本文写 git worktree:同一个仓库开出第二个目录,各自停在不同分支。本文按 Git 2.56.0。
  • 只是把修改收起来再切回原分支时,用 Git安装和常用命令(最新) 第 26 节的 git stash。分支的创建和切换见同一篇第 18 节。
  • git-worktree。

什么时候用

git stash 把未提交的修改收进仓库,当前目录可以切到别的分支,但同一时刻只有一份工作区。git worktree add 再检出一份文件到另一个目录。两个目录都能改、能编译、能提交,共用同一套提交历史和远程配置。

适合主分支上要临时看一个问题,功能分支上的修改还不想中断。看完删掉那个目录即可。

加一个目录

在主仓库里执行。新目录放在仓库外面,例如上一级的 ../blog-hotfix。放在当前仓库里面时,这些文件会在主目录里显示成未跟踪文件。

已有分支 hotfix 时,第二个参数就是分支名:

1
2
# 在 ../blog-hotfix 检出已有分支 hotfix。该分支不能已经在别的目录里
git worktree add ../blog-hotfix hotfix

从 main 新开一个分支并放到新目录:

1
2
# -b 的分支从 main 拉出,目录名可以和分支名不同
git worktree add -b hotfix ../blog-hotfix main

不写分支名时,Git 用路径的最后一段当作新分支名,起点是当前提交:

1
git worktree add ../hotfix

同一个分支不能同时出现在两个目录。再加一次会得到 already used by worktree。只要在那个目录里看文件、不占用分支时,用分离的 HEAD:

1
git worktree add --detach ../blog-build main

看现在有哪些目录:

1
git worktree list

进入新目录之后,git status、git commit、git push 和在主目录里一样。这个目录里的 .git 是一个文件,指向主仓库的 .git。删掉主仓库的 .git,这里的历史也一起没了。

提交、分支和远程配置是共用的。git stash 的条目也是共用的,在一个目录里 git stash pop 可以取走另一个目录里存的条目。每个目录有自己的暂存区和当前分支。

删掉目录

先离开该目录,回到主仓库再删。有未提交的修改时命令会拒绝。确认这些修改可以丢掉之后再加 -f。

1
git worktree remove ../blog-hotfix

直接 rm -rf 删掉目录时,主仓库里还会留着这条记录。git worktree list 仍能看到它。清理记录:

1
2
git worktree prune
git worktree list

prune 只删除已经不在磁盘上的记录。目录还在时,用 git worktree remove。

目录挪了位置、git status 报找不到工作区时,在主仓库执行 git worktree repair。