Mingyu's Library主页
2026年8月22日

第 16 课:Git Worktree 并行开发

2026-08-22 · 主题:git worktree 并行(parallel worktrees) 为什么是今天:8 月的 v2.1.x 系列移除了 subagent 并发上限,又上线了跨会话消息(第 13 课)。并行能力已经就位,但并行的地基是文件系统隔离——没有 worktree,开两个会话只会互相踩脚。今天把这块地基补上。 前置:git ≥ 2.5(worktree 支持),Claude Code v2.1.x。


为什么分支不够,worktree 才行

一个 git 仓库的工作目录同一时刻只能 checkout 一个分支。你开两个 Claude Code 会话指向同一个文件夹,它们会同时写同一份工作区——A 在改 src/auth.ts 的同时 B 把它 checkout 成了另一个版本,结果是互相覆盖、编译失败、diff 一片混乱。

worktree 的定义就是解药:同一个 .git 仓库(共享全部历史与对象),挂多个独立的工作目录,每个目录 checkout 自己的分支。git 本身会拒绝在两个 worktree 里 checkout 同一个分支——报错,而不是静默损坏。

参考:Claude Code Worktrees Guide 2026、Git Worktrees + Claude Code 2026 Playbook


技巧 1(入门):用内置 worktree 开第二条战线

Claude Code 内置了 worktree 支持,不用手写 git 命令。在会话里:

/worktree feature-auth

默认行为:在仓库根目录下创建 .claude/worktrees/feature-auth/,新建分支 worktree-feature-auth,并在该目录里启动一个 Claude 会话。

等价的纯 git 写法(想放在别处、或想自己控制分支名时用):

# 在仓库同级建一个 worktree,基于 main 新建分支
git worktree add ../myrepo-auth -b feature/auth main

# 查看当前所有 worktree
git worktree list

# 在新目录里起会话
cd ../myrepo-auth && claude

关键规则:每个 worktree 用一个全新分支。想在两个 worktree 里 checkout 同一个分支?git 会直接报错。

📎 Claude Code Docs ・ Worktrees Guide 2026


技巧 2(进阶):把「新 worktree 开箱即用」脚本化

worktree 最大的坑不是 git,是未被 git 追踪的东西不会跟过去:node_modules/、.env、venv/、构建缓存。新 worktree 一开,Claude 第一件事就是发现项目跑不起来,然后开始瞎猜。

把准备动作写成一条命令,消灭这个环节:

#!/usr/bin/env bash
# ~/bin/cwt  —  create worktree + prepare + launch
set -euo pipefail
name="$1"
root="$(git rev-parse --show-toplevel)"
dir="$(dirname "$root")/$(basename "$root")-$name"

git worktree add "$dir" -b "feature/$name" "${2:-main}"

# 复制不被追踪但必需的文件
for f in .env .env.local; do
  [ -f "$root/$f" ] && cp "$root/$f" "$dir/$f"
done

cd "$dir"
npm ci --prefer-offline    # 或 pnpm i / uv sync,按你的项目改
claude

用法:cwt auth → 建目录、建分支、搬 .env、装依赖、起会话,一步到位。

更省磁盘的做法:依赖目录用软链而不是重装(仅当各 worktree 依赖版本一致时):

ln -s "$root/node_modules" "$dir/node_modules"

⚠️ 注意:软链会让所有 worktree 共享同一份依赖。一旦某个分支要改 package.json,立刻改回 npm ci,否则你会在 A 分支调试 B 分支装的包。

📎 Shareuhack · 一人工程团队的并行工作流


技巧 3(进阶):给每个 worktree 一份「它是谁」的上下文

并行的真正风险不是文件冲突(worktree 已经解决了),而是语义冲突:两个会话各自合理,合起来重复实现了同一个工具函数,或者对同一个接口签名做了互相矛盾的假设。

对策是在每个 worktree 里放一份任务级 CLAUDE.md,明确写清边界:

<!-- ../myrepo-auth/CLAUDE.md  (与仓库根的 CLAUDE.md 叠加生效) -->
# 本 worktree 的任务边界

分支:feature/auth  ·  只做:登录/注册/会话续期

## 允许修改
- src/auth/**
- src/api/routes/auth.ts
- tests/auth/**

## 禁止修改(有并行会话正在改)
- src/billing/**   ← feature/billing worktree 正在改
- prisma/schema.prisma  ← 需要改 schema 时先停下来问我

## 约定
- 新增共享工具一律放 src/lib/,并在 PR 描述里单列一行,方便我发现重复实现

配合 hooks 把「禁止修改」变成硬约束(见第 4 课),而不只是一句提醒:

// .claude/settings.json(该 worktree 内)
{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Edit|Write",
      "hooks": [{
        "type": "command",
        "command": "case \"$CLAUDE_TOOL_INPUT_FILE_PATH\" in *src/billing/*|*schema.prisma) echo 'blocked: owned by another worktree' >&2; exit 2;; esac"
      }]
    }]
  }
}

技巧 4(高阶):并行度上限与收尾流程

并行度:2026 年中的实践经验是,单人稳定跑 4~8 个并发 worktree;再往上,瓶颈不在 Claude 而在你自己的 review 带宽。Claude Code 的作者 Boris Cherny 在年初分享过他的做法:终端里 5 个会话对应 5 个 checkout,再加 5~10 个 web/移动会话,总计 10~15 条并行。这个量级的前提是每条线的产出都能被快速判定,而不是需要你逐行读。

收尾——worktree 用完必须清掉,否则会累积成一堆半死不活的目录和分支:

# 1. 在 worktree 里正常提交 + 推送
git push -u origin feature/auth

# 2. 回到主 worktree,合并
cd "$root" && git merge --no-ff feature/auth

# 3. 删除 worktree(会同时清理 .git/worktrees 元数据)
git worktree remove ../myrepo-auth

# 4. 清理已合并的分支
git branch -d feature/auth

# 5. 定期修剪失效记录(手动 rm 过目录时用得上)
git worktree prune

合并顺序有讲究:并行分支合回主干时,先合改动面最大 / 最基础的那条(schema、共享工具、配置),再合叶子功能。反过来做,你会连着解 N 次同样的冲突。

一条实用的自查:合并前在主 worktree 跑一次 git diff main...feature/auth --stat,如果出现了 CLAUDE.md 里标为「禁止修改」的路径,说明约束没生效——先查 hook,再看代码。

📎 DevToolLab · 5 个并行 Agent 指南 ・ Claude Directory · Worktrees Guide


一句话总结

worktree 解决文件冲突,任务级 CLAUDE.md + hooks 解决语义冲突,review 带宽决定并行上限。三者缺一,并行就是在给自己制造 merge 地狱。


来源