同一個 repo 同時開兩個 Codex Agent,很快就會遇到一個看似奇怪的情況:兩邊明明各有一條 branch,為什麼還是不能放心讓它們在同一個資料夾裡一起改?

因為 branch 沒有替你複製第二份工作目錄。

branch 記的是一條開發線目前指向哪個 commit;worktree 才會多出另一份實際可編輯的目錄,並保有自己的 HEAD、index 與未提交狀態。[1][2] 兩個 Agent 如果仍然待在同一個 working directory,它們碰到的還是同一批檔案與同一份 checkout 狀態。

Codex App 把 worktree 做進多 Agent 工作流,就是為了讓同一個 repo 上的平行任務可以各自在隔離的 code copy 裡施工,而不必共用同一份本機 Git working state。[4]

Git、Branch、Worktree 與 PR 的責任邊界

Figure 1|四個概念各自處理不同問題。這是一張操作心智模型,不是 Git 官方 taxonomy。

先把四個概念放回各自的位置

如果只記名詞,很容易把 branch、worktree 和 PR 都想成「另一條 Git 路線」。實際上,它們各自管的是不同層。

名詞最適合回答的問題主要責任它不會替你完成什麼
Git這個 repo 有哪些版本歷史?commits、objects、refs 與版本資料工作目錄隔離
Branch這條開發線目前指到哪個 commit?一個會移動的 commit reference第二份專案目錄
Worktree這個 task 現在在哪份檔案狀態裡施工?額外的 working directory,以及自己的 HEAD、index、未提交狀態VM、container 或完整執行環境隔離
PR這組變更要怎麼被檢查並收進目標 branch?hosting platform 上的討論、review、checks 與 merge 流程working copy 或 branch 本身

Pro Git 把 branch 定義成指向 commit 的 lightweight movable pointer。[1] 建立 branch 只多了一個 reference,不會複製一套專案檔案。

git worktree 做的事情不同。Git 允許同一個 repository 同時掛著多個 working trees;它們仍然共享 repository 的大部分資料,但各自保有 HEAD、index 等特定狀態。[2]

PR 又在另一層。以 GitHub 為例,PR 把 head branch 的變更放進一個可討論、可 review、可跑 checks、最後決定是否合進 base branch 的協作流程。[3]

所以一個多 Agent 任務可以同時用到 branch、worktree 和 PR,但這不代表三者可以互換。

Branch 分開開發線,Worktree 分開施工空間

假設現在有兩件互不相同的工作:

Task A: refactor payment retry logic
Task B: update checkout UI

你可以先準備兩條 branch:

agent/payment-retry
agent/checkout-ui

但如果兩個 Agent 都在這裡工作:

~/project/

它們仍然共用同一個 working tree。

Agent A 正在修改檔案時,Agent B 如果 checkout 另一條 branch、restore 檔案、reset 或改動 index,操作的都是同一份目錄狀態。Git 也可能因為未提交變更而拒絕切 branch,逼你先 commit、stash 或處理 dirty state。

人類單線開發通常感覺不到這個問題,因為同一時間往往只有一個人在操作那個資料夾。兩個 Agent 可以真的同時讀檔、改檔和跑指令,共用 working tree 就變成 concurrency 問題。

換成 worktree,檔案層可以拆成:

~/project/                 -> main worktree
~/project-payment/         -> agent/payment-retry
~/project-checkout/        -> agent/checkout-ui

自己用 Git CLI 建立其中一份時,可以寫:

git worktree add ../project-payment -b agent/payment-retry main

這會建立新的 linked worktree,並從 main 建立 agent/payment-retry 給它使用。[2]

到這一步,你能確認的是:Task A 有了另一份可獨立 checkout、修改與保留未提交狀態的 working directory。

這條指令沒有順便保證其他事情。它不會證明兩個 task 最後一定能無衝突合併,也不會替兩個 app 分 port、分 database、分 queue、分 credential,更不會決定 shared file 最後由誰改。

Git 還有一個保護機制值得知道:同一條 branch 預設不能同時被多個 worktree checkout;要繞過這個檢查必須明確使用 --force。[2]

Worktree 的隔離邊界停在 Git

linked worktree 不是另一個完整 repository,也不是一台新的 VM。

Git 官方文件把共享與獨立狀態分得很清楚:linked worktrees 共用同一個 repository 的共同資料與大部分 refs,repository configuration 預設也是共享的;HEAD、index 等特定檔案才屬於個別 worktree。[2]

因此兩個 Agent 就算檔案完全分開,仍可能一起使用:

localhost:3000
postgres://localhost/dev
redis://localhost:6379

其中一個 process 可能先占住 port;兩組 test 可能一起寫同一個 development database;Worktree A 啟動的 queue consumer 也可能吃掉 Worktree B 送出的訊息。

OpenAI 在 Harness Engineering 的案例裡,另外讓 app 可以針對每個 Git worktree 個別啟動,並為每個 worktree 建立短生命週期的 observability stack,讓 logs、metrics 與 traces 跟著工作空間分開。[5]

這些隔離是 Harness 額外補上的,範圍在 application instance 與 observability。Git worktree 本身沒有替 port、database、queue、credential 或外部 side effect 建立同樣的邊界。

如果一個 task 只改檔案,worktree 可能已經夠用。如果它會啟動 server、寫資料或碰外部資源,隔離設計就還沒結束。

兩個獨立施工現場,最後還是要收斂

把兩個 Agent 放到不同 worktree 後,施工期間乾淨很多:

Agent A -> Worktree A [branch: agent/payment-retry]
Agent B -> Worktree B [branch: agent/checkout-ui]

A 的 dirty files 不會突然出現在 B 的 working directory。

但如果兩邊最後都修改:

src/payment/config.ts

合併時仍然可能產生衝突。

AgenticFlict 收集了超過 142,000 個 AI coding agent 產生的 PR,其中超過 107,000 個進入 deterministic merge simulation;作者在這個資料集裡觀察到 27.67% textual conflict rate。[6]

這個數字不是 Codex benchmark,也不是兩個 worktree 發生衝突的機率。它只能支持一個比較窄的判斷:Agent 產生的 change sets 進入整合階段時,textual conflict 是需要被工作流處理的現實情況。

兩個 Agent 使用獨立 Worktree 平行施工,但變更仍需要在 integration boundary 收斂

Figure 2|Worktree 把施工中的 working state 分開;兩組 change sets 匯合時仍需要 ownership、review、checks 與 merge。

PR 就是在這裡接手。

GitHub 的 PR 讓一條 head branch 對 base branch 提出變更,reviewer 可以檢查 diff、討論特定行、跑 checks,最後再決定是否 merge。[3] 它管理的是變更怎麼進入目標 branch,而不是替 Agent 提供另一份工作目錄。

可以把責任順序看成:

Worktree -> 產生實際修改
Branch   -> 承載這條開發線
PR       -> 提供 review 與整合入口
Base     -> 接收被接受的結果

這不是 Git 強制規定的生命週期。worktree 裡的變更可以只留在本機,branch 也不一定要開 PR。這個順序只是用來避免把工作空間、版本線和整合流程混在一起。

先切清楚誰能改什麼,再決定要不要平行

worktree 能保護兩邊的 working state,卻不會判斷哪個 Agent 應該動 shared file。

如果 Task A 和 Task B 都需要大量修改同一個核心模組、同一份 schema migration 或同一個 shared config,硬拆成兩個 worktree 只是把衝突從施工期間延後到 merge。

派工前先把三件事寫清楚:

Target paths
Shared-file owner
Merge owner

例如:

Agent A
Target: src/payment/**
Shared file: config/payments.ts -> owned by A

Agent B
Target: src/checkout/**
Shared file: config/payments.ts -> do not edit

Merge owner
Integrates A + B and resolves the shared boundary

這不需要先搞一套完整的多 Agent 治理框架。目的只是先確認兩件工作是不是真的有足夠獨立性。

「任務小就不要開 worktree」這個規則很容易失準。Git 官方本身就把平行的實驗性工作列為 worktree 的典型用途。[2] 一個十分鐘的 hotfix,如果你現在的 main working tree 正堆著兩小時尚未 commit 的 refactor,額外 worktree 反而可能最省事。

判斷重點是隔離帶來的價值,值不值得支付多一份 workspace、同步與最後整合的成本。

情況比較實際的做法
兩個 task 可以各自推進,而且都需要保留未提交狀態分 worktree
長時間 refactor 還沒收完,突然來一個獨立 hotfix即使 hotfix 很小,也值得考慮 worktree
兩個 task 大量改同一批檔案或同一個 schema先重切 scope / ownership,或序列執行
只有一個很小、清楚的 edit,沒有 dirty state 要保留單一 working tree 通常更直接
兩邊會啟動相同 service、共用 DB / queue / cacheworktree 之外再加 runtime / data 隔離
repo 高度依賴 Git submodules先確認 worktree 相容性;Git 官方文件指出 multiple checkout 的 submodule 支援仍不完整,不建議直接對 superproject 做多重 checkout。[2]
沒有人負責最後整合先指定 merge owner,再 fan-out

worktree 很適合解決「我需要另一份不互踩的施工狀態」,但不必變成每次叫 Agent 都要走的儀式。

下次開多個 Agent,先問四件事

遇到同一個 repo 要同時跑幾個 Codex task,可以快速檢查:

  1. History:每件工作最後由哪條 branch / commit line 承載?
  2. Working state:每個 worker 有自己的 worktree,還是大家共用同一個 directory?
  3. Integration:change set 在哪裡被 review、跑 checks、合進 base branch?
  4. Ownership:shared files 誰能改,最後誰負責 merge?

這四個問題拆開後,branch、worktree 和 PR 就各自回到自己的責任層。真正需要判斷的是工作怎麼切、哪些狀態仍然共用,以及什麼證據足以讓最後的變更安全收進主線。

References

  1. Git, Pro Git, 2nd Edition: Git Branching - Branches in a Nutshell. https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell
  2. Git, git-worktree Documentation. https://git-scm.com/docs/git-worktree
  3. GitHub Docs, About pull requests. https://docs.github.com/en/pull-requests/get-started/about-pull-requests
  4. OpenAI, Introducing the Codex app. https://openai.com/index/introducing-the-codex-app/
  5. OpenAI, Harness engineering: leveraging Codex in an agent-first world. https://openai.com/index/harness-engineering/
  6. Ogenrwot, D. & Businge, J., AgenticFlict: A Large-Scale Dataset of Merge Conflicts in AI Coding Agent Pull Requests on GitHub, arXiv:2604.03551. https://arxiv.org/abs/2604.03551