Git 切割方法:subtree

| | 0 Comments| 16:53
Categories:

之前在研究切割 Git Repository 的時候,曾經寫了一篇《分割 Git Repository》做紀錄,不過最近要再做處理的時候,才發現當時紀錄的方法,比較接近使用「filter-branch」這個指令來硬上;實際上 Git 本身還有提供其他的方法,可以更直覺地把 Repository 的一部分、切割出來成為一個獨立的 Repository。

這樣的功能,在 Git 裡面是所謂的 subtree。

如果要針對現有的 respository 做切割的話,基本上就是要使用 git subtree split 這個指令;例如:

git subtree split -P ModuleAPath -b "ModuleA"

上面的 git 指令的效果,就是建立出一個新的新的分支(branch)「ModuleA」,裡面只有「ModuleAPath」這個資料夾下的東西而已。

之後,則可以直接使用這個分支,或是再另外建立一個新的 repository,來專門儲存這個新建立的 branch,這樣就可以了。這邊的指令會類似:

mkdir ModuleARepo
cd ModuleARepo
git init
git pull OriginRepoPath ModuleA

而如果在 split 的指令後面不加上「-b」的話,他會把指定的路徑(ModuleAPath)當作一個獨立的 repository 來處理,而不會獨立出來;在這個概念下,其實也可以不建立出新的分支,而直接針對 subtree 進行 push 或 pull。

下面就是一個範例:

git subtree push -P ModuleAPath RemoteA master

來把 ModuleAPath 這個子資料夾的東西,推送到 RemoteA 這個 repository  的 master 分支。

附帶一提,這邊比較討厭的一點,是 TortoiseGit(官網)並不支援 subtree,所以相關的動作沒辦法用 TortoiseGit 的圖形介面來做操作,必須要使用 Git 的指令列才行。


在 Heresy 自己的經驗,使用 Git 本身的 subtree split 來做切割,算是滿方便的。不過,這樣做的缺點是切割出來的新 repository 是由單一分支來的,所以假設本來這個資料夾下面,本來有不同分支的變更紀錄,都不會被保存下來;最後留存下來的,只有單一分支,而記錄也只有用來切割的分支的紀錄而已。

相較於此,用 「filter-branch」硬上的方法,則是本來的分支結構都在,而且有較完整的紀錄。

此外,subtree split 也僅能切割出單一資料夾,沒辦法同時保有兩個資料夾;相較之下,使用 filter-branch 會有更大的自由度。

最後,透過 subtree 切割之後,和該資料夾相關的 commit 紀錄都會被複製一份,成為一條獨立的線;所以理論上再透過 subtree 切割出分支之後,應該要在使用之後,把該分支移除、以減少 repository 中重複的 commit 紀錄(SHA-1 不一樣,但是內容是相同的)。


而切出來之後要怎麼使用呢?之前 Heresy 還沒研究,這次也稍微看了一下。

基本上,要把一個外部的 repository 拿來使用,在 git 環境下可以透過 subtree 和 submodule 這兩種方法來做到。兩種不同的方法,在使用概念上有滿大的差異,而且看來也是各有優缺點。

在概念上:

  • git subtree
    • 把外部的 repository 整個包含紀錄、一起複製進來,變成單一個 repository。
    • 完成合併之後,就是單一 repository 了,所有操作都和之前一樣,沒有任何變化。
    • 要只做這個模組的更新、或是重新切出來,都會比較複雜,需要重新跑 subtree 的指令。
  • git submodule
    • 建立一個連結,在 submodule 資料夾下另外去 clone 外部的 repository 來用,實際上會是獨立的 repository。
    • 由於是採用特殊的連結架構,所以在操作上會需要特別的指令。
      • 在跟目錄下會多一個「.gitmodules」的檔案,紀錄 submodule 的資訊。
      • submodule 會指定到特定的版本,如果要更新 submodule 的內容的話,會需要另外處理。

在 Heresy 來看,submodule 比較適合用來連結外部的函式庫、或是多個專案的共用元件;而 subtree 則比較適合用來把其他的 repository 完全合併進來、放棄他的獨立性。


參考:

Leave a Reply

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *