需要同时改两个分支时,可以用 git worktree 分开目录

36 次浏览7 条回复

要一边修 bug、一边保留当前分支继续跑测试时,没必要反复 stash 和 checkout。仓库根目录可以直接开一个工作树:

git worktree add ../app-fix -b fix/cache
cd ../app-fix

# 在这个目录改代码、提交
git status

# 回到原仓库查看所有工作树
git worktree list

# 分支合并后再移除临时目录
git worktree remove ../app-fix

环境:Git 2.20+。../app-fix 目录需要还不存在,-b fix/cache 会同时创建新分支;如果分支已经存在,就把命令改成 git worktree add ../app-fix fix/cache。工作树之间共享对象库,但每个目录有自己的检出状态,比较适合并行处理互不冲突的任务。

补一个容易踩的点:每个 worktree 的未跟踪文件也是各自独立的,切过去前最好确认目标目录干净。分支还被某个 worktree 占用时,Git 也不允许直接在别处 checkout 它;合并后先 git worktree remove,再删分支会顺手很多。

uitfLv1#1

补一个容易踩的点:每个 worktree 的未跟踪文件也是各自独立的,切过去前最好确认目标目录干净。分支还被某个 worktree 占用时,Git 也不允许直接在别处 checkout 它;合并后先 git worktree remove,再删分支会顺手很多。

还有个小细节:worktree 共享的是 Git 对象库,不是工作目录,所以 node_modules、.venv 和构建产物通常还是要各自准备。想检查有没有遗留记录,可以先跑 git worktree list --porcelain;git worktree prune 只清理已经丢失的 worktree 记录,不会替你删除仍存在的目录。

ZiorLv1#2

还有个小细节:worktree 共享的是 Git 对象库,不是工作目录,所以 node_modules、.venv 和构建产物通常还是要各自准备。想检查有没有遗留记录,可以先跑 git worktree list --porcelain;git worktree prune 只清理已经丢失的 worktree 记录,不会替你删除仍存在的目录。

再补一个清理时的坑:git worktree remove 默认会拒绝删除仍有未提交改动或未跟踪文件的工作树。执行前先在对应目录跑一下 git status;--force 虽然能绕过检查,但里面的临时文件也可能一起没了,最好别当常规清理命令用。

别熬夜啦Lv1#3

再补一个清理时的坑:git worktree remove 默认会拒绝删除仍有未提交改动或未跟踪文件的工作树。执行前先在对应目录跑一下 git status;--force 虽然能绕过检查,但里面的临时文件也可能一起没了,最好别当常规清理命令用。

如果只是想拿某个提交临时跑测试,不想专门建分支,也可以用:

git worktree add --detach ../app-test <commit>

测完再 git worktree remove ../app-test。这个适合做回归对比;还是先确认目录里没有要留的改动,别顺手用 --force 清掉。

JonahLv1#4

如果只是想拿某个提交临时跑测试,不想专门建分支,也可以用:

git worktree add --detach ../app-test <commit>

测完再 git worktree remove ../app-test。这个适合做回归对比;还是先确认目录里没有要留的改动,别顺手用 --force 清掉。

还有个不太显眼的命令:如果临时 worktree 放在移动盘或网络目录,短时间不可见时可以先锁住记录:

git worktree lock --reason "external test tree" ../app-test
git worktree unlock ../app-test

这样跑 git worktree prune 时不会把它当成丢失目录清掉。普通本地目录不用锁,最后还是用 git worktree remove 收尾。

HosuLv1#5

还有个不太显眼的命令:如果临时 worktree 放在移动盘或网络目录,短时间不可见时可以先锁住记录:

git worktree lock --reason "external test tree" ../app-test
git worktree unlock ../app-test

这样跑 git worktree prune 时不会把它当成丢失目录清掉。普通本地目录不用锁,最后还是用 git worktree remove 收尾。

lock 主要是保护 worktree 的元数据,避免 prune 把暂时不可见的记录清掉,不等于目录本身已经可访问。目录恢复或重新挂载后,先用 git worktree list --porcelain 看路径是否正常,再 unlock;确认不再需要时还是走 git worktree remove,这样收尾比较稳。

FinleyLv1#6

lock 主要是保护 worktree 的元数据,避免 prune 把暂时不可见的记录清掉,不等于目录本身已经可访问。目录恢复或重新挂载后,先用 git worktree list --porcelain 看路径是否正常,再 unlock;确认不再需要时还是走 git worktree remove,这样收尾比较稳。

如果是目录被移动后路径关联异常,还可以试试 git worktree repair ../app-test,再用 git worktree list --porcelain 核对。它修的是 worktree 的元数据,不会恢复目录里的文件;确认路径和锁状态都正常后再 unlock,这时排查会更稳一点。