乐于分享
好东西不私藏

Codex app Worktrees 使用笔记

Codex app Worktrees 使用笔记

基于 OpenAI 官方文档 Codex app Worktrees 整理。

核心总结

Worktree 的价值不是替代 Local,而是把 Codex 的后台任务从日常工作目录里隔离出去。Local 继续承载当前调试、开发服务器和本地配置;Worktree 承载并行任务、实验性修改、测试补充和准备走 PR 的改动。

它的主要收益是并行和隔离。它的主要代价是环境重复:node_modules.venv.env、构建产物和本地缓存通常不会自动跟着走,新 Worktree 可能需要重新安装依赖或跑 setup scripts。

使用上可以按这个原则判断:

马上在当前目录改:Local

后台并行任务:Codex-managed Worktree

想走 PR:Worktree + Create branch here

想拿回原目录调试:Handoff to Local

长期独立环境:Permanent Worktree

Handoff 移动的是同一条 thread。因此,这条 thread 之前的对话上下文会保留,并在新的 Local 或 Worktree 环境里继续。

1. 核心理解

Codex 的 Worktree 功能,可以理解成:

让 Codex 在同一个 Git 项目里开一个项目副本,独立做任务,减少对原始项目目录的影响。

假设项目在:

C:\projects\shop-app

这是日常打开 VS Code、跑 npm run dev、手动改代码的地方。Codex 文档里叫:

Local checkout

简称:

Local

Codex 如果开 Worktree,可能会在类似这里创建一份后台目录:

$CODEX_HOME\worktrees\shop-app-xxx

这个目录里也有完整项目文件:

src

package.json

README.md

所以可以先用这个模型理解:

Local = 原来的项目目录

Worktree = Codex 另开的项目副本

2. Git 背景

Worktree 只适用于 Git 仓库。

Git 仓库就是带 .git 历史记录的项目目录。Git 里几个基础概念:

commit = 一次代码存档

branch = 一条开发线

checkout = 把某个分支或版本取出来,放到一个目录里编辑

比如:

git checkout main

意思是把当前项目目录切到 main 分支对应的代码状态。

Git worktree 允许同一个仓库有多个可编辑目录:

C:\projects\shop-app                  Local

$CODEX_HOME\worktrees\shop-app-task1  Worktree 1

$CODEX_HOME\worktrees\shop-app-task2  Worktree 2

这些目录各自有一份文件,但共享同一套 Git 历史信息,比如 commit、branch。

3. Codex Thread 是什么

Codex thread 可以理解成一条 Codex 任务对话。

例如:

线程 A:修登录 bug

线程 B:重构订单页

线程 C:补单元测试

每条线程可以绑定到 Local,也可以绑定到某个 Worktree。

所以 Codex 文档里说“move a thread”,意思是移动这条 Codex 任务对话和它相关的代码工作现场。

4. 为什么要用 Worktree

没有 Worktree 时,用户和 Codex 都在 Local 里改代码:

C:\projects\shop-app

如果 Local 正在调试登录页,Codex 同时改订单页,可能产生这些问题:

当前 dev server 的代码突然变化

Codex 修改了当前正在看的文件

用户和 Codex 同时改了同一段代码

Local 未提交改动和 Codex 的改动混在一起

有了 Worktree:

Local:用户继续做当前工作

Worktree:Codex 在后台做另一个任务

它的主要价值是:

并行

隔离

后台运行

减少干扰

5. Codex 里怎么创建普通 Worktree

普通 Worktree 在官方文档里叫 Codex-managed worktree。也可以把它理解成默认临时 Worktree。

创建方式

  1. 在 Codex app 新建线程

  2. 在输入框下面选择 Worktree

  3. 选择起始分支,比如 mainmaster、某个 feature 分支,或者当前带未提交改动的分支

  4. 提交任务

  5. Codex 创建一个 Git worktree,然后在里面工作

官方文档说,Codex 默认会让这个 worktree 处于 detached HEAD 状态。

通俗说:

Codex 基于某个 commit 开始改代码,但暂时不给这批改动创建正式分支名。

好处是不会一上来创建一堆分支。确认这批改动有用后,再点 Create branch here

6. 临时 Worktree 和永久 Worktree 的区别

官方文档分两类:

Codex-managed worktree

Permanent worktree

“临时 worktree”,对应官方的 Codex-managed worktree。它偏轻量、可丢弃,由 Codex 自动管理。

项目
Codex-managed 临时 Worktree
Permanent 永久 Worktree
创建入口
新建线程时选择 Worktree
项目侧边栏里点项目的三点菜单创建
生命周期
偏临时,Codex 管理清理
长期存在
线程关系
通常专门服务一条线程
可以从同一个永久 worktree 开多个线程
是否自动删除
可能自动删除
不会自动删除
适合场景
临时修 bug、后台跑单个任务、并行实验
长期功能开发、固定独立环境、多线程共享同一环境
是否作为独立项目出现
通常绑定在线程上
会作为自己的项目出现
Handoff 后再回去
Codex 会回到这条线程关联的同一个后台 worktree
本身就是长期项目环境

普通临时 Worktree 的特点

轻量

通常一条线程一个

Codex 默认管理

会占磁盘

可能被自动清理

删除前会保存快照

永久 Worktree 的特点

长期保留

不会因为归档线程自动删除

可以从同一个 worktree 开多个线程

适合稳定的独立开发环境

创建上的关键区别

临时 Worktree:新建线程时选 Worktree。

永久 Worktree:项目侧边栏三点菜单创建,会变成一个独立项目。

能力上的关键区别

临时 Worktree 适合一次性任务。

永久 Worktree 适合长期环境和多个线程复用。

7. Worktree 创建后能做什么

在 Worktree 里,Codex 可以像在普通项目目录里一样:

读文件

改文件

跑命令

跑测试

使用集成终端

用 Open 按钮打开 IDE 到这个 worktree 目录

如果配置了 Local Environment,Codex 可以给 worktree 跑 setup scripts。官方文档提到,这适合在 worktree 里直接安装依赖、跑验证。

环境和依赖成本提醒

Worktree 的一个常见代价是环境需要单独准备。Git worktree 共享 Git 历史,但每个 worktree 都是独立工作目录。很多被 .gitignore 忽略的文件不会自动出现。

常见例子:

node_modules

venv

.venv

.env

dist

本地缓存文件

后果是:新建 Worktree 后,Node 项目可能需要重新运行 npm installpnpm install 或 yarn install;Python 项目可能需要重新创建虚拟环境,并运行 pip install -r requirements.txt。如果依赖多、网络慢、包里有 native build,第一次启动 Worktree 会比直接用 Local 慢很多。

这不是 Worktree 的功能错误,而是隔离带来的成本:

代码隔离越彻底,依赖目录、虚拟环境、构建产物和缓存的重复成本越明显。

可以缓解,但不能完全消除:

用 Local Environment setup scripts 自动安装依赖和构建

用 lockfile 保证依赖一致

Node 项目优先考虑 pnpm 这类可复用全局 store 的工具

保留 .env.example,但不要提交真实 .env

定期清理不用的 worktree

8. 两条常见路线

路线一:一直在 Worktree 里完成

适合:

希望保持 Local 干净

可以在 Worktree 里跑测试

希望 Codex 的成果走 Git 分支、commit、push、PR

流程:

Codex 在 Worktree 改代码

点 Create branch here

提交 commit

push 到远程仓库

开 GitHub PR

路线二:Hand off 到 Local

适合:

想用原来的 VS Code 窗口检查代码

只能跑一个 dev server

数据库、本地配置、终端环境都在 Local

想把 Codex 做到一半的任务拿回原目录继续

流程:

Codex 在 Worktree 改代码

点击 Hand off

选择 Local

这条线程和相关代码改动转到 Local

后续 Codex 在 Local 继续

9. Handoff 是什么

Handoff 可以理解成:

把一条 Codex 任务的工作现场,从 Local 和 Worktree 之间迁移。

它包含两件事:

Codex 对话线程换地方继续

相关代码改动也跟着过去

例如:

Worktree 里:

src/Login.tsx 被 Codex 改了

点击 Hand off to Local

Local 里:

src/Login.tsx 也带上这批改动

这条 Codex 对话以后在 Local 继续

Handoff 和 git merge 要严格区分:

Handoff 关注:这条 Codex 任务在哪个目录继续

git merge 关注:一个分支的历史合进另一个分支

不过从用户结果看,Handoff 确实可能像“把代码合过去”。它会移动代码改动,所以可能遇到类似合并冲突的问题。

官方文档还说了一点:因为 Handoff 使用 Git 操作,.gitignore 里的文件不会跟着线程移动。

比如这些通常不会跟着走:

.env

node_modules

dist

本地缓存文件

空白新建 Worktree 和 Handoff 到 Worktree 的区别

这两种操作看起来都是进入 Worktree,但性质不同。

空白聊天新建 Worktree,更像是新开一条任务的工作现场:

新建一条 thread

选择起始分支

可选:把当前分支的未提交改动应用到 worktree

Codex 创建 detached HEAD worktree

关键点是:

即使带未提交改动,也可以不马上新建分支。

因为这是新 thread 的新工作现场,没有已有 thread 要迁移。

Hand off 已有聊天到 Worktree,更像是迁移一个已有工作现场:

把已有 thread 从 Local 移到 Worktree

聊天上下文继续保留

相关代码改动也要跟着移动

所以如果 Codex app 要求新建分支,原因通常不是“有聊天记录”本身,而是它要给这条已有 thread 的工作一个明确的 Git 归属,并避免 Local 和 Worktree 同时控制同一个 branch。

官方文档没有说所有 handoff 到 Worktree 都必须新建分支。更稳妥的理解是:

新建 Worktree thread:可以从 branch HEAD 加未提交改动生成 detached HEAD。

Handoff 已有 thread:要迁移已有 thread 和 code 状态,Codex 可能要求创建 branch 来固定这批工作。

10. Create branch here 是什么

如果想继续留在 Worktree 里工作,可以点:

Create branch here

它的作用是:

把当前 Worktree 上的改动放到一个正式 Git 分支上。

然后可以:

commit

push

开 PR

让团队 review

合进 main

比如:

Codex 在 Worktree 改了登录页

点击 Create branch here

分支名:feature/login-fix

然后提交、推送、开 PR

这条路线更像标准 Git 协作流程。

11. Handoff 和 Create branch here 的区别

操作
通俗理解
会不会马上影响 Local
是否进入正式 Git 分支流程
Handoff to Local
把任务和改动搬回原始目录继续
不一定
Create branch here
把 Worktree 成果变成一个分支
不会马上影响 Local
git merge
把一个分支合进另一个分支
看 merge 发生在哪个目录

实用判断:

想马上在原目录跑项目、调试、继续改:Handoff to Local

想保持 Local 干净、走 PR:Create branch here

想长期独立环境:Permanent worktree

12. 为什么同一个分支不能两个地方同时 checkout

Git 有一个限制:同一个 branch 不能同时被多个 worktree checkout。

例如:

Worktree 已经 checkout feature/a

Local 再 checkout feature/a

可能报错:

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

</worktree_path>

原因很具体:branch 是一个会移动的指针。commit、reset、rebase、merge 都可能移动这个指针。两个目录同时控制同一个 branch,Git 很难保证谁是权威状态。

所以官方建议:

如果想把 worktree 上的分支拿到 Local 继续,不要强行两个地方 checkout 同一分支,优先用 Handoff。

13. Handoff 会不会冲突

可能会冲突,也可能被阻塞。

虽然 Handoff 不是 git merge,但官方文档明确说它使用 Git 操作,并且会移动 thread 和相关代码。官方没有说明具体冲突 UI 和底层命令。基于 Git 操作机制,如果两个地方改了同一个文件、同一段代码,就可能冲突或被 Codex app 阻塞继续。

例子:

Local 里改了 src/Login.tsx 第 20 行

Worktree 里 Codex 也改了 src/Login.tsx 第 20 行

点击 Hand off to Local 时,Codex 需要把 Worktree 的改动带到 Local。Git/Codex 如果无法自动判断保留哪边,就可能出现冲突或阻塞。具体表现要以当前 Codex app 版本为准。

14. Create branch here 会不会冲突

创建分支这个动作通常不产生冲突。

冲突多发生在后续 merge、rebase 或 PR 合并阶段,通常在这些时候:

把 Codex 分支 merge 到 main

在 GitHub 上合 PR

把 main rebase/merge 到 Codex 分支

例子:

main 上有人改了 src/Login.tsx 第 20 行

Codex 分支也改了 src/Login.tsx 第 20 行

后续合并时就可能冲突。

15. 两类冲突的区别

路径
冲突发生时机
冲突发生地点
本质
Handoff to Local
把任务从 Worktree 搬回 Local 时
Local 工作区
移动未完成改动时可能冲突或阻塞
Create branch here
后续 merge / rebase / PR 合并时
Git 分支合并流程
两条分支历史合并时冲突

一句话:

Handoff 可能现在就让 Local 面临冲突或阻塞。

Create branch here 本身通常不冲突,冲突通常发生在后续正式合并阶段。

16. 如何减少 Handoff 冲突

Handoff 前先检查目标目录。比如准备 Hand off to Local:

cd 项目目录

git status

如果 Local 有未提交改动,先别急着 Handoff。

比较稳的做法有三种。

第一种,提交 Local 改动:

git add .

git commit -m "save local work before handoff"

第二种,stash 暂存:

git stash push -u -m "save before handoff"

第三种,继续让 Codex 留在 Worktree,走 Create branch here 和 PR。

还可以用任务边界降低冲突概率:

Local 在改登录页时,就别让 Codex 在 Worktree 也改登录页。

Local 在改业务逻辑时,可以让 Codex 去补测试或文档。

Worktree 任务不要拖太久,做完尽快 handoff、建分支或丢弃。

17. 冲突发生后怎么处理

如果看到冲突标记,通常像这样:

<<<<<<< HEAD

Local 的版本

=======

Worktree 或分支里的版本

>>>>>>> xxx

处理步骤:

  1. 打开冲突文件

  2. 判断保留哪边,或者手动写出第三种最终版本

  3. 删除 <<<<<<<=======>>>>>>>

  4. 跑测试

  5. 标记解决并提交

命令通常是:

git status

git add 冲突文件

git commit -m "resolve conflict"

如果 Git 还不熟,建议先遵守这条规则:

Local 有未提交改动时,不做 Handoff。

想安全隔离,就让 Codex 在 Worktree 里 Create branch here。

只有 Local 干净、确实想在原目录继续调试时,再 Handoff。

18. Codex 如何清理 Worktree

官方文档说,Codex 会在:

$CODEX_HOME/worktrees

下面创建 worktree。

默认保留最近 15 个 Codex-managed worktrees。可以在设置里改这个数量,也可以关闭自动删除。

Codex-managed worktree 通常不会自动删除这些:

绑定了置顶对话

线程仍在进行中

永久 worktree

可能被删除的情况:

归档了相关线程

超过配置的保留数量

删除前,Codex 会保存快照。之后重新打开相关对话时,可以恢复。

Permanent worktree 不会因为归档线程自动删除。

19. Automations 和 Worktree

官方文档还提到 automations:

Git 仓库里的 automations 会跑在专用后台 worktree

非 Git 项目的 automations 会直接跑在项目目录里

这说明 Worktree 依赖 Git。没有 Git 的项目,Codex 没有 Git worktree 可以创建。

20. 最终记忆版

Local = 原来的项目目录

Worktree = Codex 另开的项目副本

Thread = 一条 Codex 任务对话

Handoff = 把这条任务和相关代码改动换到另一个目录继续

Create branch here = 把 Worktree 里的改动变成正式 Git 分支

Codex-managed worktree = 默认临时 worktree,通常服务一条线程,可能自动清理

Permanent worktree = 长期 worktree,作为独立项目存在,可多线程复用,不自动删除

Detached HEAD = Codex 基于某个 commit 工作,暂时没有正式分支名

使用建议:

小任务、马上在当前目录改:Local

后台并行任务:Codex-managed Worktree

想走 PR:Worktree + Create branch here

想拿回原目录继续跑和调试:Handoff to Local

长期独立开发环境:Permanent Worktree

Local 有未提交改动:先 commit 或 stash,再考虑 Handoff