Git Subtree:多專案整合的實用技巧
Git Subtree 介紹
什麼是 Git Subtree?
git subtree 是 Git 內建的專案管理工具,它解決了一個常見的開發需求:
如何在專案 A 中整合專案 B 的程式碼,同時保持專案 B 的獨立性與可更新性?
假設你正在開發一個主專案,需要使用另一個獨立維護的函式庫。如果只是把那個函式庫 clone 下來後複製到主專案中,雖然可以使用,但會遇到幾個問題:無法追蹤程式碼來源、難以同步原始專案的更新、無法將改進推送回原始專案。類似的情境還包括:
- 如何將主專案中某個模組拆分成獨立的 repository 供其他專案使用?
- 如何將多個獨立的小專案整合到一個統一的大 repository 中?
Git Subtree 提供的功能可以很好地解決這些問題。它可以將一個外部 Git repository 的內容完整嵌入到你的專案的子目錄中。這些內容會真正成為你的專案的一部分(不是連結或參照),同時保留與原始專案的關聯。使用 Git Subtree 後,你的專案結構可能如下:
main-project/
├── .git/
├── src/
│ └── main.js
├── lib/
│ └── shared-library/ ← Git Subtree (來自外部 repo)
│ ├── index.js
│ └── utils.js
└── README.md
在這個例子中,lib/shared-library/ 目錄的內容來自另一個獨立的 Git repository(例如 https://github.com/user/shared-library.git),但它已經完全整合到 main-project 中。
Git Subtree 有以下幾個主要的功能特點:
- 完整整合:當其他開發者 clone 主專案時,會直接取得
lib/shared-library/的所有檔案和內容,不需要執行任何額外的初始化指令。這與 Git Submodule 不同,後者 clone 後只會得到一個空目錄的參照,需要額外執行git submodule init和git submodule update才能取得實際內容。 - 可直接修改:
lib/shared-library/是真實存在於主專案中的目錄和檔案,不是符號連結或參照。你可以直接在主專案中編輯這些檔案,所有修改都會被 Git 正常追蹤。這與 Git Submodule 不同,後者的子目錄實際上是一個獨立的 Git repository,修改時需要進入該目錄並在其 Git 環境中操作。 - 雙向同步:可以從原始專案拉取更新(使用
git subtree pull將原始shared-libraryrepository 的新版本同步到主專案),也可以將主專案中的修改推送回原始專案(使用git subtree push將你在主專案中對lib/shared-library/的改進推送回原始的shared-libraryrepository)。
Git Subtree vs Git Submodule
| 特性 | Git Subtree | Git Submodule |
|---|---|---|
| 內容儲存 | 完整複製到主 repo | 僅儲存 commit 參照 |
| Clone 行為 | 一次 git clone 即可取得所有內容 | 需要額外執行 git submodule init/update |
| 學習曲線 | 較簡單,使用標準 Git 指令 | 較複雜,需要理解 submodule 概念 |
| 歷史記錄 | 子專案歷史可選擇性保留或壓縮 | 子專案歷史獨立於主專案 |
| 檔案大小 | 主 repo 較大(包含所有內容) | 主 repo 較小(僅參照) |
| 適用情境 | 需要完整整合、簡化協作流程 | 需要明確版本控制、多專案共用 |
| 修改子專案 | 可直接在主 repo 中修改並推回 | 需要進入 submodule 目錄操作 |
Git Subtree 的兩大常見用法
1. 將外部專案整合到主專案(Add & Pull)
使用情境:在主專案中使用某個函式庫或共用模組,並且能夠定期同步上游的更新。