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。
创建方式
-
在 Codex app 新建线程
-
在输入框下面选择 Worktree
-
选择起始分支,比如
main、master、某个 feature 分支,或者当前带未提交改动的分支 -
提交任务
-
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 自动管理。
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
普通临时 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 install、pnpm 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 的区别
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
实用判断:
想马上在原目录跑项目、调试、继续改: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 可能现在就让 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
处理步骤:
-
打开冲突文件
-
判断保留哪边,或者手动写出第三种最终版本
-
删除
<<<<<<<、=======、>>>>>>> -
跑测试
-
标记解决并提交
命令通常是:
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
夜雨聆风