ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Git Worktree实战:保留未提交改动,同时开分支修Bug

Git Worktree实战:保留未提交改动,同时开分支修Bug

代码改了一半,暂时还不想提交,却需要去另一个分支修问题。常见做法是先stash,修完再恢复。这当然能用;麻烦在于,你得把当前现场收起来,再重新找回来。

Git Worktree 提供了另一种做法:当前目录先留着,再开一个目录处理另一个分支。两个任务各有自己的工作文件和暂存区,你可以分别打开编辑器。

下面用一个最小仓库演示。示例里的“修复”只是修改配置,目的是看清 Git 的行为,不涉及真实线上系统。命令在 Windows、PowerShell 7.5.4 和 Git 2.55.0.windows.5 下跑过。

先做出一个切不走的现场

找一个空目录执行下面的命令。演示会创建worktree-demo/shop-app,不要放到已有项目里运行。

mkdir worktree-demo cd worktree-demo git init-b main shop-app cd shop-app# 只设置这个演示仓库的提交身份git config--local user.name"Worktree Demo"git config--local user.email"demo@example.invalid"@("feature.search=off","checkout.retries=1")|Set-Contentapp.properties-Encoding utf8NoBOM git add app.properties git commit-m"initial configuration"git branch feature/search# main 分支随后有了一次配置变更@("feature.search=off","checkout.retries=3")|Set-Contentapp.properties-Encoding utf8NoBOM git add app.properties git commit-m"adjust checkout retries on main"# 回到功能分支,留下尚未提交的修改gitswitchfeature/search @("feature.search=on","checkout.retries=1")|Set-Contentapp.properties-Encoding utf8NoBOM git status--short--branch

这时所在分支是feature/search,app.properties有未提交的改动:

## feature/search M app.properties

再执行git switch main,会得到这段提示:

error: Your local changes to the following files would be overwritten by checkout: app.properties Please commit your changes or stash them before you switch branches. Aborting

这里特意让两个分支修改同一个文件,是为了稳定复现保护机制。并不是只要工作区不干净,Git 就一定拒绝切分支;会覆盖当前修改时,它才会拦住这次操作。

当前目录不动,给修复分支另开一个目录

仍在shop-app中执行:

git worktree add-b fix/checkout../shop-hotfix main git worktree list

这条命令里,main是新分支的起点,fix/checkout是要创建的分支,../shop-hotfix是它的工作目录。

如果分支已经存在,才使用不带-b的写法,例如git worktree add ../shop-hotfix fix/checkout。不要混用:前一种创建分支,后一种检出已有分支。

此时目录关系是这样:

6秒原创机制示意动画。工作文件、暂存区和 HEAD 各自独立,对象库与大部分引用共享;动画按实验中的目录关系绘制。

分别查看两个目录中的配置:

Get-Content./app.propertiesGet-Content../shop-hotfix/app.properties

本次实验中,前者是feature.search=on、checkout.retries=1,后者是feature.search=off、checkout.retries=3。原目录的功能改动还在,新目录拿到的是main那份已提交的内容。

现在就可以用 IDEA 或其他编辑器打开shop-hotfix。两个目录都能继续操作,不必先把功能分支里的半成品塞进一次临时提交。

修完后,别忘了把提交交回主线

下面继续修改演示配置,并在修复分支提交:

@("feature.search=off","checkout.retries=4")|Set-Content../shop-hotfix/app.properties-Encoding utf8NoBOM git-C../shop-hotfix add app.properties git-C../shop-hotfix commit-m"fix checkout retry limit"git status--short--branch

最后一个命令查看的仍是原来的shop-app。它依然显示feature/search和那处未提交修改。修复提交已经在fix/checkout上,但不会因此自动进入main。

本次真实 VS Code 截图。左侧是功能分支保留的修改,右侧是已将重试次数改为 4 并提交的修复目录;侧栏的名称用于区分两个工作目录。

实际项目还是要走团队原有的评审、合并和测试流程。Worktree 帮你安排工作目录,不能替你决定合并什么。

用完可以移除目录,分支还在

先确认修复目录里的改动已经妥善处理:

git-C../shop-hotfix status--short--branch git worktree remove../shop-hotfix git worktree list git branch--list

本次实验中,移除后只剩shop-app这个工作目录,fix/checkout分支和刚才的提交仍然存在。移除 Worktree 不等于删除分支。

remove默认也会检查未提交修改和未跟踪文件。遇到拒绝移除,先去看git status,不要为了省一步直接加--force。这个演示最后保留了原目录的未提交修改,方便继续核对;它没有被清理命令顺手抹掉。

“各开一个目录”也有边界

每个 Worktree 有自己的工作文件、暂存区和HEAD,但它们属于同一个仓库,共享对象库和大部分引用。默认情况下,同一分支已经被一个 Worktree 使用,另一个就不能再检出它。本次尝试再次检出feature/search时,Git 返回了already used by worktree。

这也是为什么给多个 AI 编程任务分目录时,应该给它们安排不同分支,并明确谁负责最后合并。目录分开,并没有消除代码层面的冲突。

运行环境也要另外安排。两个 Spring Boot 项目如果都监听同一个端口,还是会冲突;连接同一个数据库,也可能改到同一份数据。依赖目录和构建产物通常还要分别准备,不能把 Worktree 当成容器。

如果只是临时离开几分钟,stash很顺手。如果两个任务需要并排看代码、来回调试,或者要让多个 Agent 分头改不同功能,再开 Worktree 会更合适。判断的依据是你是否需要同时保留两个工作现场。

修订于2026年11月1日:补完整最小仓库、失败与收尾结果、真实IDE截图和原创关系动画,并区分工作目录与运行环境隔离。

参考:Git 官方 git-worktree 文档。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进