Git submodule的使用

最近在作一個上傳的客戶端,上傳的部分由後端同窗以 SDK 的方式提供,所以該 SDK 是在一個獨立的倉庫,那麼對於客戶端該如何方便的集成該 SDK 呢?每次 SDK 更新把代碼拷貝到客戶端倉庫?把 SDK 發佈到 npm?這就能夠考慮用 git 的 submodule。git

什麼是 submodule

submodule 是一個多項目管理工具,它容許將子項目以獨立的 git 項目添加到主項目,而主項目以 submodule 的形式擁有子項目。子項目擁有本身的 commit、push、pull,而與主項目互不干擾。主項目只須要記錄子項目的地址和所須要的 commit id,經過地址和 commit id 就可以獲得對應的子項目。github

添加 submodule

一般狀況下,咱們都有一個主項目(MainProject),在 MainProject 文件夾下執行以下命令,便可添加 submodule。npm

/*
  url: 子項目遠程地址或本地地址
  path: 子項目路徑,可省略
*/
$ git submodule add [url] [path]
例: git add submodule git@github.com:fengyueran/UploaderSDK.git ./src/UploaderSDK
複製代碼

git status 能夠看到以下信息後端

On branch master
    Changes to be committed:

        new file:   .gitmodules
        new file:   UploaderSDK
複製代碼

能夠看到多了兩個文件: .gitmodules 和 UploaderSDK。 cat .gitmodules 看到.gitmodules 儲存了 submodule 的路徑及遠程地址。緩存

[submodule "src/uploaderSDK"]
	path = src/uploaderSDK
	url = git@github.com:fengyueran/UploaderSDK.git
複製代碼

UploaderSDK 的內容爲 submodule 的 commit id。bash

Subproject commit 6b53e1840b27ca1587b96c1eb9dd5f4ff0866089
複製代碼

不難想象經過.gitmodules 和 UploaderSDK 的信息就能夠拿到 submodule 的內容了,所以咱們須要提交這個兩個文件。工具

git add .
git commit -m "add submodule"
複製代碼

克隆帶有 submodule 的項目

主要有兩個方式測試

1. 採用先克隆後更新的方式ui

和想象中的不同,直接 clone 主項目,submodule 並不會跟着 clone 下來,而只有包含 submodule 名的空文件夾。url

1)$ git clone git@github.com:fengyueran/MainProject.git
複製代碼

需再執行以下命令

2)$ git submodule init
複製代碼

輸出以下,能夠看到該命令給子項目註冊了路徑,即在主項目中的位置。此時,uploaderSDK 文件夾仍未空。

Submodule 'src/uploaderSDK' (git@github.com:fengyueran/UploaderSDK.git) registered for path 'src/uploaderSDK'
複製代碼

 再執行

//該命令並非直接更新到最新的submodule commit,而是更新至主項目所存儲存的commit(有多是較舊的commit)。
3)$ git submodule update
複製代碼

輸出以下,能夠看到 sumodule 獲得更新,更新到主項目存儲的 submodule commit,是一個遊離的 git header。

Cloning into '/Work/test/MainProject/tmp/MainProject/src/uploaderSDK'...

Submodule path 'src/uploaderSDK': checked out '6b53e1840b27ca1587b96c1eb9dd5f4ff0866089'
複製代碼

2. 採用遞歸參數--recursive

git clone git@github.com:fengyueran/MainProject.git --recursive
複製代碼

輸出以下,能夠看到主項目包括 submodule 都被 clone 下來了。

Cloning into 'MainProject'...
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (4/4), done.
Receiving objects: 100% (7/7), done.
remote: Total 7 (delta 0), reused 4 (delta 0), pack-reused 0
Submodule 'src/uploaderSDK' (git@github.com:fengyueran/UploaderSDK.git) registered for path 'src/uploaderSDK'
Cloning into '/Work/test/MainProject/tmp/MainProject/tmp/MainProject/src/uploaderSDK'...
Submodule path 'src/uploaderSDK': checked out '6b53e1840b27ca1587b96c1eb9dd5f4ff0866089'
複製代碼

修改更新 submodule

主要有兩種狀況

1. 直接在主項目中的 submodule 下修改

如上例,直接在 MainProject 下的 src/uploaderSDK 中修改,uploaderSDK 切換到工做分支,修改並提交後,能夠 checkout 到最新的 commit,也能夠不切,反正都在當前最新的 commit 上(若是想測試其餘 commit 也能夠切換到相應 commit 上),此時 MainProject 中咱們能夠看到 src/uploaderSDK 的 commit 有以下變化

-Subproject commit 6b53e1840b27ca1587b96c1eb9dd5f4ff0866089
+Subproject commit a4d6dc0457673a275b1f6cbeda6f8ff23293b9de
複製代碼

a4d6 爲修改的提交,須要注意的地方是此時 submodule 已經在最新的 commit 上了,不要再在 MainProject 中 git submodule update 進行更新了,若是進行此操做 submodule 又會回到原來的 commit(帶有減號的 commit),只須要在 MainProject 提交,並在必要的時候 push 到遠程倉庫。這種方法,非 submodule 的開發人員就不用關心 submodule 是否更新了,只須要在 MainProject 下 pull 代碼發現 submodule 有更改時執行 git submodule update(更新爲帶減號 commit)進行更新,前提是其餘開發人員提交了正確的 submodule commit。

2. 在 submodule 本身獨立的倉庫進行修改

在工做目錄克隆下 submodule 的倉庫,切換到工做分支進行修改提交併 push 到遠程倉庫。這種方法須要 submodule 開發人員告訴 MainProject 的開發人員 submodule 有更新或主動查看是否有更新,有更新時就在 MainProject 的 src/uploaderSDK 下 pull 遠程代碼(須要知道 submodule 的工做分支),快速合併後,uploaderSDK 的 commit 有以下變化,此時同 1 不要 git submodule update,而只是在 MainProject 下提交這個更改。

-Subproject commit f4573cc1bb50000779202c7f56a640b1ffc075cb
+Subproject commit 64ae6d149c0f6e3b06b8cea262c6126a7bc0887f

複製代碼

刪除 submodule

執行以下命令

  1. $ git submodule deinit
逆初始化模塊,submodule爲子模塊目錄,執行後可發現子模塊目錄被清空
$ git submodule deinit [submodule_name]
-> Cleared directory 'test2sub'
Submodule 'test2sub' (git@github.com:fengyueran/test2sub.git) unregistered for path 'test2sub'

//執行以下命令還能看到子項目信息
$ git submodule
-> -dab52c62f52353d9967619625c28e28dc4320aef test2sub
複製代碼
  1. $ git rm --cached [submodule_name]
// 刪除.gitmodules中記錄的模塊信息(--cached選項清除.git/modules中的緩存)
git rm --cached test2sub
//執行以下命令已看看不到刪除的子項目信息了
$ git submodule
複製代碼
  1. $ git commit
git commit -m "remove submodule"
複製代碼
相關文章
相關標籤/搜索