跳到主要内容
两个终端一个茶壶:手动敲的分支名,比自动生成的值钱

两个终端一个茶壶:手动敲的分支名,比自动生成的值钱

阿舟
阿舟

· 阅读约 3 分钟

上周我终于正经配了一次 worktree。配完只有一个感觉:以前嫌它小题大做,多半是我真没认真想过它的用法,以为无非是“一个仓库开两个目录”,stash 一下切分支也挺稳的。

后来看到有人写的那篇《Two Terminals, One Pot of Tea》——两个终端一个茶壶——才意识到自己嫌弃的不是麻烦,而是从没把它的核心用法看清。那位作者的做法很朴素:每个并行任务开一个 worktree,分支名、Claude 会话名、任务用途三者对齐。就这么一条规则,把“我这会到底在哪个分支上”这种心理负担整个卸掉了。

核心命令就这一条:

git worktree add -b feat/y-key ../peektea-y issue-2

一条命令把新目录、新分支、基线全办齐了。同一时间一个分支只能存在于一个 worktree,你只要按任务开 worktree,提交就只能落进它该落的分支——“不小心把修复提交到功能分支”这种事,在结构上就不存在了,不用靠自觉。

真正让我感兴趣的,是他对 Claude Code 那个 --worktree 自带命令的态度。他试过,然后弃了。原因是默认分支名是 worktree-feature-x,还基于 origin/HEAD 创建,不一定是你想要的基线和名字。

我看到这儿笑了——这个判断太有代表性。工具替你省了打几个字的功夫,却把“分支叫什么”这个本该由你掌握的信息也收走了。手动 git worktree add 看起来多敲了几个字符,换来的却是一个自己能读出来的分支名,和一条明确的基线。画外音:很多“最佳实践”之所以不好用,就是因为它太懂事,懂事到替你把选择权也收走了。

评论区还有个补刀说得我后背发凉:worktree 不解决合并冲突,它只是把冲突从“切换分支时”推迟到“合并时”。两个 agent 基于同一个过时 master 各自发明了重复的代码,这锅最后谁来背?

这我太熟了。上次我让两个会话并行改“互不相关”的模块,回到主干一看,两套功能几乎一样的工具函数。当时我以为是 prompt 没写清楚,后来才反应过来:不是。是我把“并行”想简单了。worktree 隔离的只是工作树,不是代码逻辑的边界;它也不帮兜底 .env、端口、本地数据库那些环境相关的坑——那是结构性问题,得你自己配。你以为这个功能“不相关”的部分,可能恰好是另一个功能的地基。所以别指望目录拆开了,思路也能跟着拆开。

这套流程里真正防翻车的,是作者补的那句:合并前用 diff 把改动逐行过一遍,别光看 AI 的总结——AI 可以静默删掉一行逻辑、悄悄改掉一个行为,不是它坏,是它蠢得逻辑自洽。review 时看到“删了一行”会觉得“嗯,可能是重构”,结果它删的是某个边界情况的检查。这种代价我缴过税,不想缴第二次。

反正我的结论是:worktree 解决“并行时不互踩”,不解决“并行出来的东西对不对”。前者靠一条命令在结构上兜底,后者靠你合并前的 diff 审查兜底。这俩都别省。

本期缴税:一条命令省下的时间,永远不够赔给一次没能提前预期的合并冲突。下次见。

阿舟
阿舟

写代码写到一半开始怀疑人生,靠 AI 工具续命,顺手把踩过的坑都记下来。

查看主页 →

更多「Claude Code」的实战

评论(1)

追问追问

'提交就只能落进它该落的分支'这句太绝对了。worktree 只锁分支占用,你在里面手动 checkout 其他空闲分支,提交照样飞过去。锁的是分支不是手。