前言
Git 裡面有多強大但是使用時機沒這麼廣泛的功能,submodule
(Git - Submodules) 就是其中一個。目前大多數的專案應該不會用到這個東西吧,最近也是因為部落格布景主題要換(又想換了 XD)所以才又重新再回憶這段指令。
What is submodule?
在軟體開發的過程中,有一些發展比較古老的大型專案,為了要將專案作更細緻的管理會將大型專案切分成數個小型專案,然後這些專案會交給不同的開發團對來開發,這樣做的話就可以讓一個 repo 瘦身,也可以讓多個團隊同時開發一個大型專案。而這些 submodule
又可以擁有各自的版控,但又不會跟主要的專案脫勾,在解耦的同時保有一定的連結。
還有另外一種使用 submodule
的情境,就是你的專案需要把別人的東西納入,而這依賴還不能透過套件管理程式 (比較常見的大概會是 Web 類型的專案,引入別人的樣式或是 template),需要將原始碼納入專案中,這時該怎麼處理?另外,假設對方還會更新這個東西的話,單純只把對方的原始碼 Copy 下來就顯的不切實際一點了。我們可以怎麼做呢?這個時候 submodule
就會是很好的解決方案。
新增一個 submodule
方式滿簡潔的,基本語法如下:
|
|
實際範例:
這邊假設你目前的位置就是主 repo 的根目錄。然後不需要先幫他建立空的目錄。
|
|
|
|
從這邊的資訊可以發現所謂的 submodule add
就是會把別人的原始碼給抓下來,不過入版控的內容你會發現他其實只記錄了那個 repo 的 sha1。可以 diff 一下你會發現他的獨特之處
|
|
若之前沒有加入任何 submodule 你會發現多了一個 .gitmodules
檔案裡面的內容也滿好懂得
|
|
除了新增這個檔案之外你還可以在 .git
資料夾裡的 config
檔案中發現他也有紀錄你的 submodule 資訊,內容也跟 .gitmodules
差不多
|
|
最重要的就是他會指明你專案底下哪一個路徑是別的 repo ,這點滿重要的,因為 submodule
會把別人的原始碼抓下來,但是你會發現你的 git 不會把那些檔案納入版控,畢竟那不算是他主要追蹤的對象,不過他卻會記錄這個 submodule
你是吃它哪一個 commit。
新增完之後其實就可以把這個異動當成一般的異動 commit 掉。至此,你的 repo 已經順利完成新增 submodule
的動作了。
更新已註冊的 submodule
這個情境應該也是使用 submodule
後非常常見的指令,要更新 submodule
的話 git
有提供相對應的指令。
|
|
上面這個指令適用於,別人已經把主要 repo 的 submodule
給更新,而你要把這個異動同步回你自己的 repo。
若是你自己異動了 submodule
然後要更新主 repo 用的 submodule
版本的話,就先將 submodule
的異動推上 remote。這個時候回到主 repo 下 git status
就會發現 submodule 的 commit 有異動,這個時候就可以遵循一般異動的模式入版控。
|
|
Clone 一個有 submodule 的 repo
這個情境在團隊使用時特別常見,或是你換個新電腦重新抓 repo 時也會用到。
主專案 clone 下來後應該會發現預設你不會把 submodule
裡的 repo 給一起抓下。
在 clone 主專案後於主專案的根目錄下執行以下指令
|
|
|
|
或是把這兩個command合併起來
|
|
好囉~這樣就會幫你把 submodule
的內容給抓下來了。若要確保 submodule
的內容是最新的話就依據上面寫的方式到 submodule
的資料夾用 pull
的方式更新。
如何移除 submodule?
移除 submodule
的方式比較手工一點,並沒有指令完整的支援,比較容易忘記一些手順。你需要先把 submodule
的內容給移除,這個部分他其實有提供指令。
基本語法:
|
|
範例:
這邊簡單暴力點做,所以直接 force + all 指令把所有的 submodule 給砍光
|
|
執行完後你會發現原本在 themes/hugo-clari
這資料夾底下的原始碼就被砍掉了,而 .gitmodule
檔案則是還留存著,不過 .git
裡的 config
的 submodule 資訊卻已經消失,所以 .gitmodule
裡的相關資訊要麻煩的手動刪除。做完這些後也是一樣把這些異動給 commit 掉就好。