Git Submodule 介紹與使用

自己用 Git 已經很長一段時間了,沒用過 git submodule 的話真的是對不起自己,今天來筆記 Git Submodule 一些操作步驟及說明。

git Submodule 使用時機

大家在開發新專案的時候,不知道有沒有用到其他專案的程式碼,像是 Web 專案,也許會用到 Blueprintcss CSS Framwork 或者是 Sass,這些專案目前都放在 Github 上面進行維護,以前的作法就是先 git clone 下來,把要的檔案分別複製到自己專案,可是問題來了,如果官方更新了程式碼,那自己的專案如何更新呢?難道是重複步驟把檔案複製到原來地方嗎?這樣會不會太麻煩,這時候就是需要 git submodule 來幫助大家進行程式碼的更新,這樣隨時隨地都可以取得最新的程式碼。補充說明一點,git 目前無法針對單一專案底下的單一檔案或目錄進行 clone,而必須 clone 整個目錄,這點跟 svn 有很大的不同,所以 git 可以建立各個不同的 submodule 來整合成一個大型 Project。換句話說就是: 在您的專案底下,你可以任意將其他人的專案掛載在自己任何目錄底下

建立 Git Submodule

在練習 git 指令之前請先註冊好 github 帳號,並且開一個測試 repository,建立 Submodule 非常容易,範例如下:
git submodule add  []
實際指令範例:
git submodule add https://github.com/appleboy/CodeIgniter-TW-Language user_guide
下這指令之前請注意最後面的 path 部份,請勿先建立空的目錄,也就是如果該目錄存在,就會衝突,所以並不需要額外幫 module 建立目錄,指令完成結果如下:
Cloning into user_guide...
remote: Counting objects: 32, done.
remote: Compressing objects: 100% (19/19), done.
remote: Total 32 (delta 12), reused 32 (delta 12)
Unpacking objects: 100% (32/32), done.
這時候在目錄底下打入指令 git status,你會發現多了兩個檔案需要 commit
# On branch master
# Changes to be committed:
#   (use "git reset HEAD ..." to unstage)
#
#       new file:   .gitmodules
#       new file:   user_guide
#
注意第一個檔案 .gitmodules,裡面紀錄 submodule 的對應關係,我們實際打開看內容:
[submodule "user_guide"]
    path = user_guide
    url = https://github.com/appleboy/CodeIgniter-TW-Language
裡面寫的很清楚,之後如果要清除 sub module 也是要從這檔案移除相關設定,接著就是直接 commit 到 project 底下吧
git commit -a -m "first commit with submodule codeigniter user guide" && git push
接著回去看 github 網站就會多出一個小圖示了 git_submodule 最後還是需要初始化 init submodule,透過底下指令來達成,否則 git 不知道你有新增 module
git submodule init

clone project with Git Submodule

我們還是拿上面的例子來測試,首先還是一樣用 git clone 來下載程式碼:
git clone git@github.com:appleboy/test.git test2
可是你有沒有發現 user_guide 這 sub module 是空目錄,這時候就是要透過 git submodule 來下載程式碼
[freebsd][root][ /home/git/test2 ]# git submodule init
Submodule 'user_guide' (https://github.com/appleboy/CodeIgniter-TW-Language) registered for path 'user_guide'
[freebsd][root][ /home/git/test2 ]# git submodule update
Cloning into user_guide...
remote: Counting objects: 32, done.
remote: Compressing objects: 100% (19/19), done.
remote: Total 32 (delta 12), reused 32 (delta 12)
Unpacking objects: 100% (32/32), done.
Submodule path 'user_guide': checked out '7efead6378993edfaa0c55927d4a4fdf629c4726'
注意上面,有沒有看到 git submodule init 來設定 .git/config,在接著用 git submodule update 來更新檔案,可以打開 .git/config 可以發現多了底下資料:
[submodule "user_guide"]
    url = https://github.com/appleboy/CodeIgniter-TW-Language

更新已安裝 module

一樣切換到 sub module 目錄,接著做 git pull
cd user_guide/
git pull origin master
這時候我們切回去上層目錄,執行 git status
# On branch master
# Changed but not updated:
#   (use "git add ..." to update what will be committed)
#   (use "git checkout -- ..." to discard changes in working directory)
#
#       modified:   user_guide (new commits)
我們有了 new commit,有沒有發現與 git submodule add 的時候一樣,這時候我們需要同步 sub module commit ID 到 parent,所以一樣執行 git commit && git push 即可。
git commit -a -m "first commit with submodule codeigniter user guide" && git push
最後可以透過 statu 來看看是否有相同的 commit ID
git submodule status

移除 Sub module

移除方式非常容易,上面有提到的檔案都必需要經過修改 1. 移除目錄
git rm --cached [目錄]
git rm [目錄]
2. 修改 .gitmodules,移除不需要的 module
vi .gitmodules
3. 修改 .git/config,移除 submodule URL
vi .git/config
4. 執行 commit
git add . && git commit -m "Remove sub module"
5. 最後 syn module 資料
git submodule sync

總結歸納

git submodule 可以用在跟其他團隊一起合作開發時候,我們只需要知道大的 git,一些細部的 sub module 就可以讓其他團隊在繼續往下開,相當方便。另外也避免每當要更新檔案的時候,還需要重複 clone 加上 cp 資料到對應目錄。 Reference: Git Submodule 的認識與正確使用! Pro git: git submodule