Skip to content

Git Worktree 支持

在独立工作区中运行 CodeBuddy,实现并行开发和安全隔离。

概述

Git worktree 允许在同一仓库中同时拥有多个工作目录,每个目录可以检出不同的分支。CodeBuddy Code 利用这一特性提供:

  • 并行开发:在不影响主工作区的情况下进行实验性开发
  • 安全隔离:AI 的所有更改都在独立目录中进行
  • 零存储开销:worktree 共享 Git 对象,不会复制整个仓库
  • 子代理隔离:支持多个 AI 子代理在独立 worktree 中并行工作
  • tmux 集成:可选在独立的 tmux 会话中运行
  • 非 Git 支持:通过 WorktreeCreate/WorktreeRemove hooks,SVN、Perforce 等项目也能使用 worktree 隔离

快速开始

bash
# 自动生成名称创建 worktree
codebuddy --worktree

# 指定名称创建 worktree
codebuddy --worktree feature-auth

# 指定基础分支创建 worktree
codebuddy --worktree --worktree-branch origin/develop  # 基于远程 develop 分支
codebuddy --worktree --worktree-branch feature/foo     # 基于本地 feature/foo 分支

# 在 tmux 会话中运行(推荐用于长时间任务)
codebuddy --worktree --tmux

# 基于 PR/MR 创建 worktree(用于代码审查)
codebuddy --worktree "#123"                                    # GitHub PR 编号
codebuddy --worktree "https://github.com/owner/repo/pull/123" # GitHub PR 链接
codebuddy --worktree "https://gitlab.com/owner/repo/-/merge_requests/456" # GitLab MR 链接
codebuddy --worktree "https://cnb.woa.com/owner/repo/-/pulls/789" # CNB PR 链接

在会话中创建

已启动 CodeBuddy Code 会话后,可以通过自然语言请求创建 worktree:

> start a worktree
> work in a worktree
> 启动 worktree

AI 会自动调用 EnterWorktree 工具创建隔离工作目录并切换过去。

注意:只有明确提到 "worktree" 时才会触发,说 "帮我开一个分支" 或 "修复这个 bug" 不会自动创建 worktree。

CLI 参数

参数说明示例
--worktree [name]创建并进入 worktree--worktree--worktree my-feature
--worktree-branch <branch>指定基础分支(需配合 --worktree--worktree-branch origin/develop--worktree-branch feature/foo
--tmux在 tmux 会话中运行(需要安装 tmux)--worktree --tmux
--tmux-classic使用传统 tmux 模式(不使用 popup)--worktree --tmux --tmux-classic

工作流程

创建 Worktree

当使用 --worktree 参数启动时:

  1. CodeBuddy 在 .codebuddy/worktrees/ 目录下创建新的 worktree
  2. 确定基础分支:
    • 如果指定了 --worktree-branch origin/xxx,基于远程分支 origin/xxx
    • 如果指定了 --worktree-branch xxx,基于本地分支 xxx
    • 如果未指定,默认基于远程默认分支(通常是 origin/mainorigin/master
  3. 自动创建对应的分支(如 worktree-feature-auth)
  4. 将工作目录切换到 worktree
  5. 执行初始化(复制设置、创建符号链接、复制 .worktreeinclude 文件等)

分支不存在时的行为

  • 如果指定的分支(远程或本地)不存在,会打印警告并自动降级到远程默认分支继续创建
  • 不会中断启动流程

退出时的选择

当你退出 worktree 会话时,CodeBuddy 会检测变更并提供选项:

  • 保留 Worktree:保留所有更改和分支,可以稍后继续
  • 删除 Worktree:清理 worktree 和关联分支
  • 保留但退出 tmux:(tmux 模式)保留 worktree 但关闭 tmux 会话

变更检测

退出前,CodeBuddy 会检测:

  • 未提交的文件变更
  • 未推送的提交

如果没有任何变更,worktree 会自动清理。

配置

settings.json 中配置 worktree 行为:

json
{
  "worktree": {
    "symlinkDirectories": ["node_modules", ".next", ".cache", "dist"]
  }
}

配置项

配置项说明默认值
symlinkDirectories从主仓库符号链接到 worktree 的目录[]

符号链接目录可以避免在每个 worktree 中重复安装依赖,节省时间和磁盘空间。

同步本地忽略文件(.worktreeinclude)

.env.local.env.development 等本地配置文件通常被 .gitignore 排除,但新 worktree 中同样需要它们才能正常运行。

解决方式:在仓库根目录创建 .worktreeinclude 文件,列出需要复制的文件(语法与 .gitignore 相同):

gitignore
# .worktreeinclude
# 列出需要复制到新 worktree 的本地文件

# 环境变量
.env.local
.env.development.local
.env.test.local

# 本地 IDE 配置
.vscode/settings.json

# 本地证书或密钥(如有)
certs/localhost.pem

每次创建新 worktree 时,这些文件会自动从主仓库根目录复制过去。复用已有 worktree 时不会重新复制

提示:.worktreeinclude 应该提交到 Git,这样团队成员都能受益。

Hook-based Worktree

默认情况下,worktree 功能依赖 Git 内置的 git worktree 命令。对于使用 SVN、Perforce 或没有版本控制的项目,可以通过配置 WorktreeCreate / WorktreeRemove hooks 来使用 worktree 隔离功能。

决策优先级

1. 配置了 WorktreeCreate hook? → 使用 hook 创建(即使在 Git 仓库中也优先使用 hook)
2. 在 Git 仓库中?              → 使用 git worktree
3. 都不满足?                   → 报错并提示配置 hook

核心规则

  • Hook 优先于 Git:配置了 WorktreeCreate hook 后,即使在 Git 仓库中也走 hook,不走 git worktree
  • 创建失败不降级:WorktreeCreate hook 失败时不会回退到 git worktree,直接报错
  • 删除失败不阻塞:WorktreeRemove hook 失败只记录警告,不阻止退出流程

配置方式

.codebuddy/settings.json(项目级)或 ~/.codebuddy/settings.json(全局)中配置:

json
{
    "hooks": {
        "WorktreeCreate": [
            {
                "hooks": [
                    {
                        "type": "command",
                        "command": "bash ~/.codebuddy/hooks/worktree-create.sh"
                    }
                ]
            }
        ],
        "WorktreeRemove": [
            {
                "hooks": [
                    {
                        "type": "command",
                        "command": "bash ~/.codebuddy/hooks/worktree-remove.sh"
                    }
                ]
            }
        ]
    }
}

两个 hook 独立配置——可以只配 WorktreeCreate 不配 WorktreeRemove(此时退出时不会自动清理,会提示手动删除目录)。

输入数据(stdin)

Hook 脚本通过 stdin 接收 JSON 格式的上下文数据。

WorktreeCreate 输入

json
{
    "hook_event_name": "WorktreeCreate",
    "session_id": "abc123def456",
    "cwd": "/Users/user/project",
    "transcript_path": "/Users/user/.codebuddy/sessions/abc123/transcript.md",
    "name": "feature-auth"
}
字段说明
nameworktree 名称(用户指定或系统自动生成)
cwd当前工作目录
session_id当前会话 ID
transcript_path对话记录文件路径

WorktreeRemove 输入

json
{
    "hook_event_name": "WorktreeRemove",
    "session_id": "abc123def456",
    "cwd": "/Users/user/project",
    "transcript_path": "/Users/user/.codebuddy/sessions/abc123/transcript.md",
    "worktree_path": "/tmp/codebuddy-worktrees/feature-auth"
}
字段说明
worktree_path要删除的 worktree 绝对路径

输出与 Exit Code

WorktreeCreate

  • stdout:必须输出创建好的 worktree 绝对路径(取最后一行非空行)
  • stderr:可输出日志,不影响路径解析
  • exit code 0:成功,解析 stdout 中的路径
  • exit code 非 0:创建失败,报错并退出(不降级到 git worktree)
bash
# 正确示例:日志输出到 stderr,路径输出到 stdout
echo "Initializing SVN checkout..." >&2
echo "/home/user/.codebuddy/worktrees/feature-auth"

WorktreeRemove

  • 没有决定控制:任何 exit code 都不会阻止退出流程
  • 失败仅记录警告日志

退出行为差异

与 Git worktree 不同,hook-based worktree 退出时始终显示 keep/remove 菜单,不做变更检测(因为非 Git 项目没有 git status)。

Hook 脚本模板

WorktreeCreate (~/.codebuddy/hooks/worktree-create.sh):

bash
#!/bin/bash
set -e

INPUT=$(cat)
NAME=$(echo "$INPUT" | jq -r '.name')
CWD=$(echo "$INPUT" | jq -r '.cwd')

WORKTREE_PATH="$HOME/.codebuddy/worktrees/$NAME"
mkdir -p "$WORKTREE_PATH"

# 在这里添加 VCS 初始化逻辑(SVN checkout、P4 sync、目录复制等)
cp -r "$CWD"/* "$WORKTREE_PATH/" 2>/dev/null || true

# 最后一行输出绝对路径到 stdout(必需)
echo "$WORKTREE_PATH"

WorktreeRemove (~/.codebuddy/hooks/worktree-remove.sh):

bash
#!/bin/bash

INPUT=$(cat)
WORKTREE_PATH=$(echo "$INPUT" | jq -r '.worktree_path')

# 安全检查:确保路径在预期范围内
if [[ "$WORKTREE_PATH" != "$HOME/.codebuddy/worktrees/"* ]]; then
    echo "Refusing to remove path outside worktrees directory: $WORKTREE_PATH" >&2
    exit 1
fi

rm -rf "$WORKTREE_PATH"

提示:脚本依赖 jq 解析 JSON。macOS:brew install jq,Linux:apt install jq

实战示例

SVN 项目

json
{
    "hooks": {
        "WorktreeCreate": [
            {
                "hooks": [
                    {
                        "type": "command",
                        "command": "bash -c 'INPUT=$(cat); NAME=$(echo $INPUT | jq -r .name); DIR=\"$HOME/.codebuddy/worktrees/$NAME\"; svn checkout https://svn.example.com/repo/trunk \"$DIR\" >&2 && echo \"$DIR\"'"
                    }
                ]
            }
        ],
        "WorktreeRemove": [
            {
                "hooks": [
                    {
                        "type": "command",
                        "command": "bash -c 'cat | jq -r .worktree_path | xargs rm -rf'"
                    }
                ]
            }
        ]
    }
}

无 VCS 的项目(目录复制)

json
{
    "hooks": {
        "WorktreeCreate": [
            {
                "hooks": [
                    {
                        "type": "command",
                        "command": "bash -c 'INPUT=$(cat); NAME=$(echo $INPUT | jq -r .name); CWD=$(echo $INPUT | jq -r .cwd); DIR=\"$HOME/.codebuddy/worktrees/$NAME\"; cp -r \"$CWD\" \"$DIR\" && echo \"$DIR\"'"
                    }
                ]
            }
        ],
        "WorktreeRemove": [
            {
                "hooks": [
                    {
                        "type": "command",
                        "command": "bash -c 'cat | jq -r .worktree_path | xargs rm -rf'"
                    }
                ]
            }
        ]
    }
}

tmux 集成

使用 --tmux 参数可以在独立的 tmux 会话中运行 CodeBuddy:

bash
# 基本用法
codebuddy --worktree --tmux

# 使用传统模式(不使用 popup)
codebuddy --worktree --tmux --tmux-classic

tmux 要求

  • tmux 版本 3.2 或更高(支持 popup 功能)
  • 如果版本较低,会自动回退到传统模式

退出 tmux 会话

  • Ctrl+D 或输入 /exit 退出 CodeBuddy
  • tmux 会话会根据你的选择保留或关闭

目录结构

your-repo/
├── .codebuddy/
│   └── worktrees/
│       ├── feature-auth/      # worktree 目录
│       │   ├── node_modules -> ../../node_modules  # 符号链接
│       │   └── ...
│       └── fix-bug-123/
├── .worktreeinclude           # 定义需要复制的本地文件(建议提交)
└── ...

手动管理 Worktree

CodeBuddy Code 在会话退出时会自动处理 worktree 的清理。但有时需要在会话外手动管理——比如清理残留的 worktree,或者需要更灵活地控制分支和目录位置。

在会话外清理 Worktree

直接使用 Git 命令清理:

bash
# 查看当前所有 worktree
git worktree list

# 删除指定 worktree(worktree 内没有未提交改动时)
git worktree remove .codebuddy/worktrees/feature-auth

# 强制删除(有未提交改动时)
git worktree remove --force .codebuddy/worktrees/feature-auth

# 同时删除对应的分支
git branch -D worktree-feature-auth

# 清理失效的 worktree 引用(目录已删但 Git 还记着)
git worktree prune

用 Git 直接创建 Worktree

有时需要检出已有分支,或者把 worktree 放到仓库目录之外,可以绕开 CodeBuddy Code 直接用 Git 创建,然后再在里面启动会话:

bash
# 新建分支并创建 worktree(放在仓库外)
git worktree add ../project-feature-a -b feature-a

# 检出已有分支
git worktree add ../project-bugfix bugfix-123

# 进入 worktree,启动 CodeBuddy Code
cd ../project-feature-a && codebuddy

# 用完后清理
git worktree remove ../project-feature-a

这种方式适合需要把 worktree 放在特定位置、或者复用现有分支的场景。

子代理隔离

当让 CodeBuddy Code 启动多个子代理并行工作时,可以让每个子代理运行在独立的 worktree 中,避免文件冲突。

isolation: worktree 是什么

在自定义 Agent 的 frontmatter 中加上 isolation: worktree,每次用 Task 工具启动这个 Agent 时,系统会自动为它创建一个独立的 worktree,而不是在主仓库目录里直接运行。

这意味着:

  • 多个子代理可以同时修改同名文件,互不影响
  • 主仓库目录保持干净,子代理的临时改动不会污染它
  • 子代理完成后,worktree 按需保留或删除

创建隔离型自定义 Agent

.codebuddy/agents/ 目录下创建 Markdown 文件:

markdown
---
name: isolated-worker
description: 在独立 worktree 中工作,不影响主仓库
isolation: worktree
---

你在一个独立的 git worktree 中运行。
请专注完成分配给你的任务,完成后汇报结果。

使用效果

主 Agent 用 Task 工具启动该 Agent 时,会自动为它创建独立的 worktree。多个子代理可以同时工作,即使修改了相同的文件也不会冲突。

子代理完成后:

  • 没有变更:worktree 自动删除
  • 有变更:worktree 保留,主 Agent 会收到 worktree 位置信息

验证隔离效果

> 使用 isolated-worker agent,在当前目录创建 test.txt,写入 "hello"

检查结果:

bash
# 主仓库里没有这个文件
ls test.txt
# → No such file or directory ✓

# 文件在子代理的 worktree 里
ls .codebuddy/worktrees/agent-xxx/test.txt
# → 存在 ✓

典型使用场景

场景一:基于特定分支开发

问题:需要在 develop 分支上开发新功能,而不是基于 main 分支。

解决方案:

bash
# 基于远程 develop 分支创建 worktree
codebuddy --worktree feature-xxx --worktree-branch origin/develop

# 基于本地分支创建(保留本地未推送的提交)
codebuddy --worktree feature-yyy --worktree-branch my-local-branch

场景二:并行处理紧急 Bug

问题:正在开发新功能,代码改了一半,突然需要修紧急 bug。

解决方案:

bash
# 终端 1:继续开发新功能
codebuddy --worktree feature-payment

# 终端 2:专门修 bug,互不干扰
codebuddy --worktree hotfix-login-crash

两个 worktree 同时打开,互不影响。bug 修完提交 PR,再回到功能开发。

场景三:高风险重构

问题:想尝试大规模重构,但不确定能否成功,不想污染主仓库。

解决方案:

bash
codebuddy --worktree refactor-esm

在会话中:

> 帮我把 src/core 目录从 CommonJS 迁移到 ESM

结果:

  • 成功:提交,推 PR,合并
  • 失败:退出时选择 "Remove worktree",所有改动一键丢弃

场景四:审查 PR

问题:想在本地跑一下同事的 PR 代码,但不想污染工作目录。

解决方案:

bash
codebuddy --worktree "#456"

在会话中:

> 帮我看看这次 PR 改了什么,有没有潜在问题
> 运行一下测试

审查完直接退出,worktree 自动清理。

场景五:并行任务

问题:有多个独立任务(写文档、加测试、开发新接口),想分别推进。

解决方案:

bash
codebuddy --worktree task-docs --tmux
codebuddy --worktree task-tests --tmux
codebuddy --worktree task-new-api --tmux

每个 worktree 让 AI 专注做一件事,配合 tmux 实现真正并行工作。

场景六:子代理协作

问题:大型任务需要多个 AI 并行处理不同模块。

解决方案:

首先创建隔离型 Agent(见上文 "子代理隔离" 章节),然后:

> 使用三个并行的 api-worker 子代理:
  第一个处理 src/api/user/ 目录
  第二个处理 src/api/order/ 目录
  第三个处理 src/api/product/ 目录

三个子代理各自在独立 worktree 中工作,即使修改了共享文件也不会冲突。

常见问题

Q: --worktree-branch 应该传远程分支还是本地分支?

严格区分:

  • --worktree-branch origin/xxx → 使用远程分支(会先 fetch 最新代码)
  • --worktree-branch xxx → 使用本地分支(保留本地未推送的提交)

如果指定的分支不存在,会打印警告并降级到远程默认分支,不会中断启动。

Q:worktree 会占用很多磁盘空间吗?

不会。所有 worktree 共享 Git 对象数据库,只需要存储工作文件本身。如果配置了 symlinkDirectories,大型目录也会共享,几乎不占额外空间。

Q:复用已有 worktree 时,.env.local 等文件还会重新复制吗?

不会。复用时直接进入已有目录,跳过初始化。如需同步新配置,需删除 worktree 后重建:

bash
git worktree remove --force .codebuddy/worktrees/my-feature
git branch -D worktree-my-feature
codebuddy --worktree my-feature

Q:worktree 里的提交会影响主仓库吗?

不会。worktree 有独立分支,提交只在该分支上。要合并到主分支,需走正常 PR 流程或手动 git merge

Q:创建 worktree 中途断开了,留下残缺目录怎么办?

bash
git worktree remove --force .codebuddy/worktrees/<>
git branch -D worktree-<>

然后重新创建即可。

Q:symlinkDirectories 配置了但没生效?

复用已有 worktree 时不会重新初始化。删除旧 worktree 重建一次即可。

Q:子代理隔离是安全沙箱吗?

不是。子代理在文件层面隔离,但权限与主 Agent 相同,理论上可操作 worktree 之外的文件。这个功能的目的是防止多个 Agent 之间的文件冲突,而非安全限制。

Q:配置了 WorktreeCreate hook 后还能用 Git Worktree 吗?

不能同时使用。Hook 优先级高于 Git——一旦配置了 WorktreeCreate hook,所有 worktree 操作都走 hook,即使在 Git 仓库中也是如此。要恢复使用 git worktree,删除 settings.json 中的 WorktreeCreate 配置即可。

Q:只配了 WorktreeCreate 没配 WorktreeRemove 会怎样?

创建正常工作,但退出时不会自动清理。系统会提示 worktree 目录保留在哪里,需要手动删除。

Q:Hook 脚本执行失败了怎么办?

WorktreeCreate 失败会直接报错,不会降级到 git worktree,检查脚本的 stderr 输出排查问题。WorktreeRemove 失败只记录警告,不影响退出流程。

Q:在非 Git 项目中使用 hook-based worktree,退出时为什么没有自动清理?

hook-based worktree 退出时始终显示 keep/remove 菜单,不进行变更检测(因为非 Git 项目没有 git status)。需要手动选择是否删除。

注意事项

  • Git 仓库或 Hook--worktree 需要 Git 仓库或配置 WorktreeCreate hook(非 Git 项目如 SVN、Perforce 可通过 hook 支持)
  • 分支命名:自动创建的分支以 worktree- 为前缀
  • 清理:长时间未使用的 worktree 不会自动清理,需要手动删除或使用 /rewind 命令
  • 符号链接:某些工具可能不支持符号链接的目录,请根据项目需求配置

相关文档