Adding a Feature to a Release Line with Git Branches and Worktrees
主要開發線已經往前進行,但上線中的舊版本臨時需要增加一項功能。這項工作一開始看似簡單,實際處理後卻可能需要補相容程式、調整資料格式或修正其他細節。
如果直接在上線 revision 修改,之後很容易忘記哪些提交還要帶回主要開發線;如果只建立一個 detached worktree,修改又沒有明確的 branch 可以保存、推送與審查。
適合這種情境的做法是:從上線 revision 建立具名 branch,並把該 branch 取出到獨立 worktree。
Branch 與 worktree 不是二選一
Git branch 是 repository 內的一個具名版本指標,可以提交、推送、審查、合併或 cherry-pick;worktree 則是 repository 之外看得到的工作目錄,裡面有取出的檔案,以及該工作目錄自己的 HEAD 與 index。
| 工具 | 責任 |
|---|---|
| Branch | 保存這項功能的提交歷程,之後可推送、審查及帶回其他版本線 |
| Worktree | 提供獨立的檔案、建置產物與編輯環境,不必切換目前工作目錄的 branch |
| Revision | 決定新 branch 從哪一個上線版本開始 |
兩者的生命週期也不同:移除 worktree 只會清除額外工作目錄,不會自動刪除 branch;branch 上的提交仍留在 repository 中。
Branch 是建立在 worktree 裡嗎?
不是。branch 不屬於某個 worktree,它屬於共同的 Git repository。worktree 只是把該 branch 取出並使用它。
下列指令把兩個動作合併成一步:
1
2
3
4
git -C ~/projects/sample-app worktree add \
-b feature/release-extra-feature \
~/worktrees/sample-app-release-feature \
release/1.x
Git 依序進行以下工作:
- 在
sample-apprepository 找到release/1.xrevision。 - 建立
feature/release-extra-featurebranch,初始位置指向該 revision。 - 建立
~/worktrees/sample-app-release-feature工作目錄。 - 在新 worktree 取出並綁定
feature/release-extra-feature。
進入新目錄後,可以確認目前 branch:
1
2
cd ~/worktrees/sample-app-release-feature
git branch --show-current
輸出應為:
1
feature/release-extra-feature
這不是「worktree 裡面另外藏了一個 branch」,而是該 worktree 的 HEAD 指向 repository 共同管理的 branch。此時在 worktree 執行 git commit,會讓 feature/release-extra-feature 往前移動;其他 worktree 也能立刻看到這個 branch 與新提交。
同一件事也能拆成兩個指令,兩種寫法在概念上相同:
1
2
3
4
5
6
git -C ~/projects/sample-app branch \
feature/release-extra-feature release/1.x
git -C ~/projects/sample-app worktree add \
~/worktrees/sample-app-release-feature \
feature/release-extra-feature
git worktree add -b 只是把「建立 branch」與「建立並取出 worktree」合併,通常較不容易漏掉其中一步。
為之後帶回主要開發線保留提交
在 worktree 內實作時,應把功能、相容處理與測試整理成目的清楚的提交。完成上線版功能後,可以依版本線差異選擇處理方式:
- 只需要其中幾個提交時,在主要開發線使用
git cherry-pick <commit>。 - 整條 branch 都適合納入,而且歷史關係單純時,才考慮 merge。
- 若主要開發線已有不同實作,先比較行為與測試,再人工整合,不應假設 Git 能自動解決語意差異。
worktree 的價值在於保留兩套工作環境;能否順利把修改帶回去,則取決於 branch 上的提交是否小而完整、測試是否能說明預期行為。
何時只用 detached worktree?
如果只是讀取舊 revision、重現問題或執行一次性測試,不準備保留修改,可以建立 detached worktree:
1
2
3
git -C ~/projects/sample-app worktree add --detach \
~/worktrees/sample-app-investigation \
release/1.x
但只要工作可能需要提交、推送、審查或套回其他版本線,就應使用具名 branch。否則 detached HEAD 上的提交較容易失去清楚的用途與後續處理位置。
使用上的限制
Git 官方文件與個人技術文章都提到,worktree 共享 object database 與 refs,但各有自己的工作目錄及 index。同一個 branch 原則上不能同時被兩個 worktree 取出。
多一套 worktree 也代表多一份建置產物與工具狀態,而且容易在錯誤目錄執行指令。因此目錄名稱應標明用途,操作前可以執行:
1
2
git status --short --branch
git worktree list
工作完成後,應透過 Git 移除 worktree,不要直接刪除目錄:
1
2
git -C ~/projects/sample-app worktree remove \
~/worktrees/sample-app-release-feature
此時 branch 仍然存在。確認它已經合併或不再需要後,才能另外決定是否刪除 branch。
結論
當上線版需要補功能,而且這些修改之後可能還要帶回主要開發線時,最適合的流程是:
- 從正確的上線 revision 建立具名 branch。
- 用 worktree 取出該 branch,保留原本的開發環境。
- 在 worktree 內完成實作、測試與提交。
- 以 merge、cherry-pick 或人工整合,把需要的提交帶回主要開發線。
branch 才是修改歷程與後續整合的載體;worktree 是讓這條 branch 擁有獨立工作目錄的工具。git worktree add -b 則是一次完成這兩項設定的便捷指令。