Git:临时并行改两个分支,可以试试 `worktree`

24 次浏览7 条回复

有时候一个仓库里主线还在跑着,旁边又想临时切到另一个分支看点东西。来回 checkout 容易把工作区搅乱,Git 自带的 worktree 可以把同一个仓库检出到另一个目录。

环境:Git 2.30+。可以在一个测试目录里跑:

mkdir worktree-demo && cd worktree-demo
git init
printf 'hello\n' > note.txt
git add note.txt
git commit -m 'init'

git switch -c feature-a
printf 'feature a\n' > a.txt
git add a.txt
git commit -m 'add a'

git switch main
git worktree add ../worktree-feature-a feature-a

然后看一下:

ls ../worktree-feature-a
git worktree list

这样 worktree-demo 还在 main,旁边的 ../worktree-feature-afeature-a。两个目录各干各的,比频繁切分支安静一点。

用完可以删掉:

git worktree remove ../worktree-feature-a

这个适合临时并行看代码、跑对比,别把它当成复制仓库的替代品就行。

这个确实挺适合临时救火。补一个小点:如果 worktree 对应的分支已经合掉、目录也手动删了,git worktree list 里可能还会留记录,可以用:

git worktree prune

清一下。还有就是同一个分支不能同时被两个 worktree 检出,这个报错第一次见可能会懵一下。

还有个小用法我觉得挺顺手:如果是想从当前点拉一个新分支出来,可以直接:

git worktree add -b fix-login ../repo-fix-login HEAD

这样新目录和新分支一次建好,不用先 branchadd。目录名最好带上分支用途,不然 worktree 多了以后真的容易分不清。

再补个容易忘的点:worktree 多了以后,先看一眼当前都挂在哪儿会比较省心:

git worktree list --porcelain

脚本里要处理的话,--porcelain 比默认输出稳一点。平时手动看就普通 git worktree list 够了。

还有一点可以提醒下:git worktree remove 遇到里面还有未提交改动时会拒绝删除,这个保护挺有用的。

真确定不要了再加 --force,不然最好先进去看一眼:

git -C ../worktree-feature-a status

我觉得 worktree 最大的好处就是主工作区不用被打断,但也因为目录分散了,删之前确认一下状态会稳很多。

还有个实际小坑:每个 worktree 都是独立工作目录,所以依赖目录、构建产物这些也会各放一份。

比如 Node 项目切出去以后,旁边那个目录通常还得自己跑一次:

npm install
# 或 pnpm install

如果项目很大,磁盘占用会涨得挺快。临时修 bug 很爽,长期堆很多个 worktree 就要记得定期收一收。

如果只是想临时看某个历史提交,其实也可以不新建分支,直接开一个 detached 的 worktree:

git worktree add --detach ../repo-old HEAD~3

看完再 git worktree remove ../repo-old。这种适合查回归点、对比老版本;如果准备改代码并提交,还是建个有名字的分支更不容易乱。

还有个偏少见但有用的命令:worktree 放在外接盘、临时目录或者某个同步目录里,短时间不想被 prune 清掉,可以先锁一下:

git worktree lock ../worktree-feature-a --reason "keep for review"

后面不用了再:

git worktree unlock ../worktree-feature-a

平时本地随手开的分支一般用不上,但共享机器或者目录会被定期清理时,这个能少一点意外。