TellWorldAI 世界档案
问档案English

首页›实践›实践

实践

Claude Code 并行开发:用 git worktree 同时跑多个会话

用 `claude --worktree` 让每个 Claude Code 会话拥有独立的 git worktree,文件各改各的。这篇讲启动、环境准备、清理,以及隔离的边界。

这篇适合谁、读完能做到什么

适合想同时让两三个 Claude Code 会话改同一个仓库、又不希望它们的文件修改互相踩到的开发者。读完你能用一个参数开出隔离的工作目录,知道会话结束时怎样清理,也知道隔离管不到哪些地方。

worktree 是什么,和并行会话怎么配合

git worktree 是同一个仓库的另一个工作目录。它有自己的文件和分支,但与主检出(main checkout)共享提交历史和远程仓库[1]。把每个 Claude Code 会话放进各自的 worktree,每个会话就拿到一份独立的文件副本去编辑:一个会话做新功能,另一个修 bug,两边的改动不会落在同一份文件上[1]。

开始前要准备什么

  • 一个 git 仓库。worktree 是 git 的功能,项目必须先是 git 仓库。
  • 信任这个目录。交互式运行时,如果以前没在这个目录里用过 Claude,先在目录里运行一次 claude,接受信任对话框;否则 --worktree 会报错退出。非交互的 -p 模式会跳过这项检查[1]。
  • 一条 .gitignore 规则。官方建议把 .claude/worktrees/ 加进去,避免 worktree 里的内容在主检出里显示成未跟踪文件[1]。
  • 每个 worktree 里都要装依赖。它是一份全新的检出,依赖和环境都要在里面重新准备[1]。

这几项里最容易漏的是最后两条:不装依赖,新会话就跑不起来;不配 .worktreeinclude,.env 之类的文件就会缺失。

第一步:开两个隔离会话

  1. 在仓库根目录运行带名字的命令:
claude --worktree feature-auth
  1. Claude 会在 .claude/worktrees/feature-auth/ 下建一个 worktree,分支名为 worktree-feature-auth,然后在里面启动[1]。
  2. 另开一个终端,换一个名字再运行一次,就得到第二个互不干扰的会话[1]。

如果省略名字,Claude 会生成类似 bright-running-fox 的名字[1]。

新 worktree 里缺的文件怎么办

新 worktree 里没有 .env 这类未纳入 git 的文件。如果每个 worktree 都要用到它们,可以在项目根目录放一个 .worktreeinclude,语法和 .gitignore 相同,Claude 创建 worktree 时会把匹配的文件复制进去[1]。只有同时匹配模式、又被 gitignore 忽略的文件才会复制,已经被 git 跟踪的文件不会重复复制[1]。

下面是一个例子,复制两个环境变量文件和一份密钥配置:

.env
.env.local
config/secrets.json

会话内切换 worktree

除了命令行参数,也可以在会话里直接让 Claude 进入 worktree。它会调用 EnterWorktree 工具创建一个;要切换到 .claude/worktrees/ 下的另一个 worktree,把目标路径传给这个工具即可[1]。

如果目标路径在 .claude/worktrees/ 之外,Claude Code 会先请你批准。EnterWorktree 的权限规则,或者选择「不再询问」,都不能跳过这个提示,只有 bypassPermissions 模式会跳过[1]。

hooks 在这里有个坑:进入 worktree 之后,hook 命令里的 ${CLAUDE_PROJECT_DIR} 仍指向会话启动时的项目根目录。要拿到当前工作目录,得读 hook 输入 JSON 里的 cwd 字段[1]。

隔离是怎么执行的

会话在 worktree 里时,Claude Code 会拦下下面几类操作:

  • 对主检出的 Edit、Write、NotebookEdit 调用;
  • 工作目录解析到主检出的 Bash、PowerShell、Monitor 命令;
  • 通过 git -C、--git-dir、GIT_DIR、GIT_WORK_TREE,或先 cd 进主检出,把 git 指到主检出的命令[1]。

让子智能体各用一个 worktree

子智能体(subagent)可以在自己的 worktree 里运行,并行修改就不会互相冲突。在自定义子智能体的 frontmatter 里加上 isolation: worktree,它每次都会在独立 worktree 中运行。.claude/agents/ 下的文件可以这样写[1]:

---
name: refactorer
description: Applies mechanical refactors across many files
isolation: worktree
---

子智能体的临时 worktree 如果没有改动,结束时会被自动删除;有改动的则保留,直到定期清理能在不丢失工作的前提下把它删掉[1]。定期清理会删除早于 cleanupPeriodDays 设定天数的子智能体和后台会话 worktree,但凡还有未跟踪或已改动的文件、或未推送的提交,就保留不删[1]。

会话结束时怎么清理

交互式 worktree 会话退出时,Claude 会检查 worktree 里有没有删除后会丢失的内容。没有内容的未命名会话,worktree 会被自动删除;命名的会话则会先问你[1]。

如果里面有内容,Claude 会问你保留还是删除。保留会留下目录和分支;退出时打印的 claude --worktree <name> --resume 可以让你之后再回到这个会话[1]。

想手动删,就用 git worktree remove。文件有未提交或未跟踪的改动时加 --force;如果 git 因为锁定而拒绝,先运行 git worktree unlock[1]。

也可以直接用 git 创建

不用 Claude 的参数,直接用 git 创建 worktree 也行,然后在里面启动 Claude:

git worktree add ../project-feature-a -b feature-a
cd ../project-feature-a
claude

这条命令会在新分支上创建 worktree[1]。

基础分支和拉取请求

默认情况下,新 worktree 从仓库的默认分支切出。把 worktree.baseRef 设为 "head",就改为从当前本地 HEAD 切出,未推送的提交和功能分支的状态会一起带过去[1]。

想基于某个拉取请求开工作区,可以在 --worktree 后面写 # 加编号,例如 claude --worktree "#1234"。引号是为了防止 shell 把 # 当成注释。Claude 会从 origin 拉取这个 PR 的头提交,worktree 建在 .claude/worktrees/pr-<编号> 下[1]。

限制和常见问题

并行会话多了以后,问题往往出在启动位置。index.lock 错误、LFS 指针文件这类报错,大多能在启动前检查出来:先确认在 worktree 根目录启动,再确认大文件已经拉取。

  • **index.lock 错误**:默认情况下,如果在 worktree 的子目录里运行 claude,git 命令会报 index.lock 错误。开启沙箱后,git commit 等命令能在 worktree 根目录的会话里正常工作[1]。
  • 共享的东西:worktree 和主检出共享 .git 目录、项目级插件和权限审批。在 worktree 里选择「是,且不再询问」某条 Bash 命令,这条规则会写进主检出的 .claude/settings.local.json[1]。
  • Git LFS:如果用 git lfs install --local 装过 LFS,Claude 创建的 worktree 里会是 LFS 指针文件,不是真实文件。在 worktree 里运行 git lfs pull 即可取回[1]。

下一步

子智能体隔离的完整说明,以及 worktree 的其他细节,都可以直接看官方文档[1]。

来源

  1. 1
    Run parallel sessions with worktreesAnthropic Claude Code docs

引用本页: Claude Code 并行开发:用 git worktree 同时跑多个会话. TellWorld, https://www.tellworld.net/zh/practice/practice-claude-code-worktrees. 更新于 2026-11-14

相关动态