Claude Code 多实例并发与冲突处理 — Q&A

1 阅读3分钟

Q1:用户在终端输入 claude 后,能否在其他窗口再运行一个 claude

可以。 两个 claude 进程各自独立运行:

  • 每个 claude 是独立的 Node.js 进程,拥有独立的 REPL 和 session ID
  • 会话存储在 ~/.claude/sessions/ 下,每个 session 独立目录,不会冲突

唯一可能的限制: MCP 服务器如果绑定固定端口(如 localhost:3000),第二个进程会因端口被占用而启动失败。但多数 MCP 服务器使用 stdio 模式(不占端口)或动态分配端口,通常不构成问题。

典型场景: 一个窗口跑长期任务(代码分析、批量重构),另一个窗口做临时问答或 review。


Q2:如果两个窗口需要修改同一个文件,会出现什么情况?

后写入的覆盖先写入的,先做的修改丢失,没有自动合并。

冲突时序

窗口A: 读取 main.tsx → 内容 v1
窗口B: 读取 main.tsx → 内容 v2 (基于相同版本 v1)
窗口A: 写入修改 → 文件变成 A 的版本
窗口B: 写入修改 → 文件变成 B 的版本(覆盖了 A 的修改)

后果

场景结果
修改不同区域后保存的覆盖整个文件,先保存的修改丢失
修改同一区域后保存的生效,先保存的被覆盖

防御机制

  • 没有文件锁,没有 git 合并,没有冲突检测
  • Agent 工具的 worktree 隔离提供了并行修改方案:
    • 启动隔离 agent 时创建 git worktree(git worktree add
    • 不同 agent 在不同 worktree 中修改同一文件
    • 最终通过 git merge 合并

Q3:git merge 合并的时候有冲突怎么办?

没有自动冲突解决逻辑。 冲突时 worktree 被保留,通知给模型/用户手动处理。

流程

agent 执行完毕
  → hasWorktreeChanges(worktreePath, headCommit)
    → git status --porcelain           # 检查未提交变更
    → git rev-list --count HEAD..HEAD  # 检查新提交
  → 有变更 → 不删除 worktree
  → 把 { worktreePath, worktreeBranch } 格式化为通知插入消息流

无变更时

没有变更 → removeAgentWorktree()
  → git worktree remove 删除目录
  → git branch -D worktree-xxx 删除分支

有变更时

worktree 保留,路径和分支名通过 XML 标签通知给模型:

<task_notification>
  <worktree_path>/repo/.claude/worktrees/agent-a1234567</worktree_path>
  <worktree_branch>worktree-agent-a1234567</worktree_branch>
</task_notification>

模型收到通知后可以选择指导用户手动合并,或用户自行处理:

cd /repo/.claude/worktrees/slug-name
git add . && git commit -m "..."
cd /repo
git merge worktree-slug-name
# 解决冲突 → git add → git commit
git branch -d worktree-slug-name

Q4:如果用户不处理这个冲突,相关分支是否会永远存在?

有变更的分支会永久保留,不会被自动清理。

自动清理机制

启动后约 10 分钟,后台任务调用 cleanupStaleAgentWorktrees(),默认清理超过 30 天(可配置 cleanupPeriodDays)未使用的 ephemeral worktree。

匹配清理的模式

agent-a<7位hex>      ← agent 工具创建的工作树
wf_<uuid>-<n>        ← 工作流创建的工作树
bridge-<id>          ← bridge 工作树
job-<name>-<8hex>    ← 模板任务工作树

安全闸门(永不自动删除有变更的 worktree)

// 检查 1:有未提交变更 → 跳过
git status --porcelain -uno
// 输出非空 → 不删除

// 检查 2:有未推送的本地提交 → 跳过
git rev-list --max-count=1 HEAD --not --remotes
// 有提交不在远程上 → 不删除

总结

状态自动清理
有未提交修改不会删除
有本地提交但未 merge/push不会删除
有冲突未解决不会删除
worktree 干净无变更30 天后自动删除

结论: 不处理的冲突分支会永久留在磁盘上,唯一的清理方式是用户手动解决冲突后删除,或确认无变更后等待自动清理。


参考

  • src/utils/worktree.ts — worktree 创建、变更检测、清理逻辑
  • src/tools/AgentTool/AgentTool.tsx — cleanupWorktreeIfNeeded 回调
  • src/tools/AgentTool/agentToolUtils.ts — runAsyncAgentLifecycle 任务完成处理
  • src/utils/cleanup.ts — cleanupStaleAgentWorktrees 调用入口
  • src/utils/backgroundHousekeeping.ts — 延迟 10 分钟启动后台清理