前言
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 掉就好。