OpenAI Codex 中文文档(4.14更新)
联系我
官方文档

工作树

在 Codex App 中利用 Git 工作树,让 Codex 并行处理多个任务

在 Codex App 中,工作树让 Codex 能在同一项目里并行执行多个互不干扰的独立任务。对于 Git 仓库,自动化任务 会运行在专用后台工作树中,从而避免与你当前正在进行的工作冲突。对于未受版本控制的项目,自动化任务会直接运行在项目目录中。你也可以手动在某个工作树上开启线程,或者使用交接功能在本地检出与工作树之间移动线程。

什么是工作树

工作树只适用于属于 Git 仓库的项目,因为它底层直接使用的是 Git worktree。一个工作树可以让你创建仓库的第二份检出副本。每个工作树都有自己完整的文件副本,但它们共享关于提交、分支等元数据的 .git 信息,因此你可以并行检出并处理多个分支。

术语

  • 本地检出(Local):你当前项目目录中的主工作副本。
  • 工作树(Worktree):由 Codex 管理的额外 Git worktree 检出目录。
  • 交接(Handoff):把线程连同相关代码一起在本地检出与工作树之间安全迁移的操作。

为什么要用工作树

  1. 在不打扰你当前本地环境(Local)的前提下,与 Codex 并行工作。
  2. 让后台任务先排队运行,而你可以继续专注于前台工作。
  3. 等你准备好审查、测试或更直接协作时,再把线程交接回本地检出(Local)。

开始使用

工作树依赖 Git 仓库。请先确认你所选项目位于 Git 仓库中。

  1. 选择 Worktree(工作树)

    在新线程视图里,在输入框下方选择 Worktree。如果需要,也可以额外选择一个 本地环境,让该工作树在创建后自动运行初始化脚本。

  2. 选择起始分支

    在输入框下方选择一个要作为工作树基线的 Git 分支。它可以是你的 main / master,也可以是某个功能分支,甚至可以是当前这个带有未暂存本地改动的分支。

  3. 提交提示词

    提交任务后,Codex 会基于你选定的分支创建一个 Git 工作树。默认情况下,Codex 会在 detached HEAD(分离头指针) 状态下工作。

  4. 选择继续工作的地方

    当你准备好继续时,可以选择一直在工作树里工作,也可以把线程交接回本地检出。无论是切到 Local(本地模式),还是从 Local(本地) 切回工作树,交接功能都会同时移动线程和代码。

在本地检出(Local)与工作树(Worktree)之间切换

工作树的使用体验和本地检出很接近,区别主要在于它们在工作流中的角色。你可以把 Local 视作前台,把 Worktree 视作后台。交接功能用来在两者之间转移线程。

在底层,交接功能会处理把工作安全地从一个检出目录移动到另一个检出目录所需的 Git 操作。这里的关键限制是:Git 不允许同一分支同时在两个位置被检出。如果你已经在某个工作树中检出了一个分支,那么你就不能同时在本地检出中再检出它,反过来也一样。

实际工作中,常见有两种路径:

  1. 一直在工作树中完成工作。当你可以直接在工作树中完成验证时,这条路径最合适,例如你已经通过本地环境初始化脚本把依赖和工具准备好了。
  2. 把线程交接回本地检出(Local)。当你想把线程带回前台,例如需要在自己常用的 IDE 中检查改动,或你的应用只能运行一个实例时,就适合走这条路径。

方案 1:一直在工作树中工作

如果你希望改动始终留在工作树中,可以在该线程头部点击 Create branch here(在此创建分支),把当前工作树转成一个真正的分支。

之后你就可以在这个工作树里提交改动、推送分支到远端,并在 GitHub 上创建拉取请求(PR)。

你还可以通过线程头部的 “Open” 按钮把 IDE 打开到这个工作树,或者使用集成终端,在工作树目录里完成其余工作。

带有分支控制和工作树详情的线程视图

带有分支控制和工作树详情的线程视图

请记住,一旦你在某个工作树上创建了一个分支,就不能在任何其他工作树中检出这个分支,包括你的本地检出。

方案 2:把线程交接回本地检出(Local)

如果你想把线程带回前台,在该线程头部点击 Hand off(交接),然后把它移动到 Local

这个路径适合以下场景:你想在自己熟悉的 IDE 窗口里阅读改动、运行既有开发服务器,或者在你平时使用的本地环境中验证结果。

Codex 会自动处理把线程从工作树安全迁移到本地检出所需的 Git 步骤。

每个线程会长期绑定同一个关联工作树。如果你之后再把线程交接回工作树,Codex 会把它送回那个同一个后台环境,这样你可以从上次停下的地方继续。

把线程从工作树移动到 Local 的交接对话框

把线程从工作树移动到 Local 的交接对话框

你也可以反向操作。如果你当前正处于 Local(本地),但想把前台腾出来,可以用 Hand off(交接) 把线程移动到某个工作树。这样 Codex 就能在后台继续工作,而你可以把本地注意力切回别的事情。

由于交接(Handoff)依赖 Git 操作,任何被 .gitignore 忽略的文件都不会随着线程一起移动。

高级细节

Codex 托管型工作树与永久工作树

默认情况下,线程使用的是 Codex 托管工作树(Codex-managed worktree)。这类工作树的设计目标是轻量、可丢弃。通常一个 Codex 托管工作树只服务于一个线程;如果你之后再把线程交还给工作树,Codex 会把它送回原来的那个工作树。

如果你需要长期存在的环境,可以从侧边栏项目右侧的三点菜单创建永久工作树。它会作为一个独立项目存在。永久工作树不会被自动删除,而且你可以在同一个工作树上启动多个线程。

Codex 如何替你管理工作树

Codex 会把工作树创建在 $CODEX_HOME/worktrees 下。起始提交是你创建线程时所选分支的 HEAD 提交。如果你选择的是带有本地改动的分支,这些未提交改动也会被应用到新工作树中。这个工作树本身不会被检出成某个分支,而是处于 detached HEAD(分离头指针) 状态。这样 Codex 就能在不污染你分支列表的前提下创建多个工作树。

分支限制

假设 Codex 在某个工作树中完成了一部分工作,你随后点击 Create branch here 在那里创建了 feature/a 分支。现在你想把它切到本地检出里。如果你直接尝试检出这个分支,就会看到下面的错误:

fatal: 'feature/a' is already used by worktree at '<WORKTREE_PATH>'

要解决这个问题,你需要在工作树那边改检出另一个分支,而不是继续让 feature/a 保持在工作树中。

如果你计划在本地检出中使用这个分支,请改用交接功能,把线程移动到 Local,而不是试图让同一个分支同时在两个地方保持检出状态。

为什么会有这个限制

Git 会阻止同一个分支同时在多个工作树中被检出,因为分支本质上是一个单一的可变引用(refs/heads/<name>),它代表“某个工作树当前检出的状态”。

当一个分支被检出后,Git 会把该分支的 HEAD 视为由这个工作树所拥有,并要求诸如提交、reset、rebase、merge 等操作以明确定义、可串行化的方式推进这个引用。如果允许多个工作树同时检出同一个分支,就会带来谁来更新这个分支引用的歧义和竞态条件,进而可能导致提交丢失、索引不一致,或冲突处理语义不清。

因此 Git 通过“一条分支一次只能属于一个工作树”的规则,保证每个分支都只有一个权威工作副本;与此同时,其他工作树仍然可以通过 detached HEAD(分离头指针)或独立分支安全地引用同一批提交。

工作树清理

工作树可能会占用大量磁盘空间。每个工作树都有自己的一套仓库文件、依赖、构建缓存等。因此 Codex App 会尽量把工作树数量维持在一个合理范围内。

默认情况下,Codex 会保留最近的 15 个 Codex 托管工作树。你可以在设置中修改这个上限,或者关闭自动删除,改为自己管理磁盘占用。

Codex 会尽量避免删除仍然重要的工作树。以下情况下,Codex 托管工作树不会被自动删除:

  • 有一个已固定(pinned)的对话绑定到了该工作树
  • 线程仍在进行中
  • 该工作树是永久工作树

以下情况下,Codex 托管工作树会被自动删除:

  • 你归档了与之关联的线程
  • 为了维持你设置的工作树数量上限,Codex 需要删除较旧的工作树

并且在删除 Codex 托管工作树之前,Codex 会先保存一份该工作树上工作的快照。如果你重新打开一个其工作树已被删除的会话,界面会提供恢复选项。

常见问题

我能控制工作树创建到哪里吗?

目前不能。Codex 会统一把工作树创建在 $CODEX_HOME/worktrees 下,以便持续一致地管理它们。

我可以在 Local 和 Worktree 之间来回移动线程吗?

可以。在线程头部使用 Hand off(交接),就能把线程在本地检出和工作树之间来回移动。Codex 会处理环境迁移所需的 Git 操作。如果你之后再把线程交还给工作树,Codex 会把它送回原来那个关联工作树。

如果工作树被删掉了,线程会怎样?

即使底层工作树目录已经被删除,线程本身仍然可能保留在历史记录中。对于 Codex 托管型工作树,Codex 会在删除前保存快照;当你重新打开对应线程时,界面会提供恢复选项。永久工作树在其线程归档后不会被自动删除。


来源:https://developers.openai.com/codex/app/worktrees