← Back to Blog
Coding中

git worktree

在 AI agent 滿天飛的時代,重新認識 git 的物件模型,利用 worktree 提升自己生產力。

2026.03.18·6 min read·1,422 words

AI 演變下的開發轉換

在 AI 快速發展下,軟體業開發速度也越來越快,如果手邊 token 數量夠的情況下,平行作業情況也越來越常見。 雖然我很不喜歡這種不斷 context switch ,不過身為打工人,也只能激發自己潛能做 multitasking。

在驅動多個 agent 在同一專案底下,最怕的就是改到同一區塊
比如說 A 想要改新增點餐系統,B 想要新增商品品項,兩者都要改到結帳系統,兩者又互相沒溝通,各自改各自的。

此時我們就想要把檔案實體分開,而不是只靠分支作為區隔。

git 是如何記錄

在實際了解 git worktree 運作之前,我們先了解 git 是如何解決工程師們協作以及版本控制的。

Git is a content-addressable filesystem. Great. What does that mean? It means that at the core of Git is a simple key-value data store.

Git 邏輯是把檔案都做成 Blob (Binary Large Object),用內容的 SHA-1 作為 key 存進 .git/objects/ 裡。
換句話說,Git 把檔案 snapshot 下來作為比對基準。

整個 object database 由四種物件組成:

物件內容比喻
blob檔案的原始位元組一份檔案內容
tree一群 blob 與其他 tree 的清單一個資料夾
commit指向一個 root tree、parent commit、作者、訊息一張快照
tag指向 commit 的具名標籤書籤
commit ── tree ── blob (README.md)
                └─ tree (app/) ── blob (page.tsx)
                                └─ blob (layout.tsx)

只要兩個檔案內容完全一樣,它們在 .git/objects/ 裡就是同一個 blob — 不管它在哪個資料夾、哪個 branch、哪個 commit。 這個「內容定址」的特性就是後面 worktree 能成立的關鍵:物件庫只要一份就夠。

git branch

A branch in Git is simply a lightweight movable pointer to one of these commits.

Git 很明確指出分支只是一個指向而已,他把當前分支對於檔案指向記錄下來,所以切換分支換言之花費很少,單純把指向箭頭換成另一個 SHA 值。

$ cat .git/refs/heads/main
8d32ff7a4c5e9b1d2f3e4a5b6c7d8e9f0a1b2c3d

所以 git branch feature-x 幾乎是零成本的 — 它就是寫一行檔案。HEAD 又是另一個指標,指向「我現在站在哪一個 branch」:

$ cat .git/HEAD
ref: refs/heads/main

當切換分支時 git checkout feature-x,Git 做的事情其實是:

  1. 把 HEAD 改成指向 refs/heads/feature-x
  2. 用 feature-x 那個 commit 的 tree,把 working directory 跟 index 重新刷成那個版本

關鍵在第 2 步 — working directory 只有一份。所以 stash → checkout → pop 才會變成日常,因為 Git 預設只能讓你「站在一個地方」。

git worktree

git worktree 就是把上面那條限制鬆開:一個 .git,可以同時對應多個 working directory。

A git repository can support multiple working trees, allowing you to check out more than one branch at a time.

每個 repo 預設有一個 main worktree,用 git worktree add 新增的叫 linked worktree。 linked worktree 的目錄下不會有 .git/ 資料夾,而是一個 .git 檔案,內容只是一行指向原本 repo 的路徑:

$ cat ../site-hotfix/.git # 對目前site-hotfix worktree底下git做cat
gitdir: /Users/me/projects/nextjs-blog/.git/worktrees/site-hotfix

所以多開幾個 worktree 並不會多複製整個 object database,也不用重新 fetch。 唯一的限制是:同一個 branch 只能被一個 worktree checkout,因為 Git 不允許兩個地方同時對同一個 ref 推進。

常用指令

# 基本用法
git worktree add -b < 本地分支名稱 > < 資料夾路徑 > < 遠端分支 >
 
# 在 ../hotfix 開一個新的 worktree資料夾,使用的是release分支
git worktree add ../hotfix release/1.2
 
# 新建 branch 並 checkout 到 ../feature-x
git worktree add -b feature-x ../feature-x main
 
# 看目前有哪些 worktree
git worktree list
 
# 移除一個 worktree
git worktree remove ../hotfix
 
# 手動刪過目錄就用 prune 清殘骸
git worktree prune

實際流程

如果單純使用 worktree,資料夾容易比較髒亂一點,我們會期望有一個 root folder 建立,裡面的資料夾就會是各個分支(worktree)
為了達成這目的,我們會建立一個裸露的 repo(Bare repo)

mkdir project && cd project
git clone --bare url .bare
echo "gitdir: .bare" > .git
 
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
git fetch
設定說明
  • .bare/:隱藏的 Git 核心資料庫
  • .git:純文字檔,指向 .bare,讓你能在 Root 直接下 git 指令
  • fetch 設定:讓 bare repo 也能正確追蹤所有遠端分支
config fetch 說明

修改 origin 這個遠端節點的 fetch 規則。 因為一開始是使用 --bare 來 clone,Git 預設的行為不會像一般 clone 那樣建立遠端追蹤分支(也就是 refs/remotes/origin/*)。這行指令強迫 Git 建立對應關係,確保之後從遠端拉取更新時,遠端的分支能正確地映射到本地的 origin/* 追蹤分支上。


所以我們就會有一個 root folder,底下都是平行的分支資料夾

Project
├── dev
├── feat
│   ├── JIRA-03
│   ├── JIRA-05
├── fix
│   ├── JIRA-01
│   ├── JIRA-02
├── main
├── refactor
│   ├── JIRA-04
└── release
    ├── 0.1.0
    ├── 0.1.1
    ├── 0.1.2
    ├── 0.2.0
    ├── 0.2.1
    ├── 0.3.0
    ├── 0.4.0
    ├── 0.4.1
    ├── 0.4.2
    ├── 0.4.3
    ├── 0.5.0
    ├── 0.5.1
    ├── 0.5.2
    ├── 0.6.0
    └── 0.6.1

這樣開發情況下就會從舊有的 git switch branch 變成實體資料夾之間的移動
換句話說在終端機裡面就可以透過開不同資料夾的 panel 進行平行開發且檔案間互不影響。

回到 AI 並行的場景

繞了一圈,回到並行開發的問題:多個 agent 如何同時開發?

git worktree add -b feat/order-system ../site-agent-a main
git worktree add -b feat/menu-items ../site-agent-b main
# 各自跑各自的 agent,各自 commit 到自己的 branch

.git 是共用的,所以 commit 都會回到同一個 object database;branch 是隔離的;working tree 是分開的,所以能在 main worktree 繼續改別的東西。

設定說明
  • node_modules / .next / venv 不會跨 worktree 共用。只有 .git 是共用的,所以這些檔案需要重新安裝。
  • .env.local 不會跟著走。沒有被 git trace 的設定檔不會出現在新 worktree,新增完要手動 cp 一份過去。

還有遇過的問題是如果忘記切資料夾,已經開發到一半了如何切出去。
可以一樣做 git stash -u,加上-u 把 untrack 檔案也一起 stash 起來,接著按照前面步驟一樣開 worktree 資料夾進去再 pop 出來就可以了。

References

last edited 2026.03.18·© 2026 tylerastro·built by hand