使用qtcreator中的git_Git中submodule的使用
背景
面對比較復雜的項目,我們有可能會將代碼根據功能拆解成不同的子模塊。主項目對子模塊有依賴關系,卻又并不關心子模塊的內部開發流程細節。
這種情況下,通常不會把所有源碼都放在同一個 Git 倉庫中。
有一種比較簡單的方式,是在當前工作目錄下,將子模塊文件夾加入到 .gitignore 文件內容中,這樣主項目就能夠無視子項目的存在。這樣做有一個弊端就是,使用主項目的人需要有一個先驗知識:需要在當前目錄下放置一份某版本的子模塊代碼。
還有另外一種方式可供借鑒,可以使用 Git 的 submodule 功能,也是這篇文章的主題。
實際上 Git 工具的 submodule 功能就是建立了當前項目與子模塊之間的依賴關系:子模塊路徑、子模塊的遠程倉庫、子模塊的版本號。
使用流程
假定我們有兩個項目:project-main 和 project-sub-1,其中 project-main 表示主項目,而 project-sub-1 表示子模塊項目。
其中 project-main 的遠程倉庫地址為 https://github.com/username/project-main.git,而 project-sub-1 的遠程倉庫地址為 https://github.com/username/project-sub-1.git。
接下來,我們希望在 project-main 中添加 project-sub-1 ,而又保持 project-sub-1 自身獨立的版本控制。
1.創建 submodule使用 git submodule add <submodule_url> 命令可以在項目中創建一個子模塊。
進入項目 project-main ,輸入:
? project-main git:(master) git submodule add https://github.com/username/project-sub-1.git正克隆到 '/path/to/project-main/project-sub-1'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
展開對象中: 100% (3/3), 完成.
此時項目倉庫中會多出兩個文件:.gitmodules 和 project-sub-1 。
前者的內容是這樣的,事實上就是子模塊的相關信息;而后者那個文件,實際上保存的是子模塊當前版本的版本號信息。
[submodule "project-sub-1"]path = project-sub-1
url = https://github.com/username/project-sub-1.git
如果此前項目中已經存在 .gitmodules 文件,則會在文件內容中多出上述三行記錄。
事實上,此時在 .git/config 文件中也會多出一些信息,在 .git/modules 文件夾下也會多出一份內容。
通常此時可以使用 git commit -m "add submodule xxx" 提交一次,表示引入了某個子模塊。提交后,在主項目倉庫中,會顯示出子模塊文件夾,并帶上其所在倉庫的版本號。
2.獲取 submodule上述步驟在創建子模塊的過程中,會自動將相關代碼克隆到對應路徑,但對于后續使用者而言,對于主項目使用普通的 clone 操作并不會拉取到子模塊中的實際代碼。
使用以下命令進行克隆,完成后 project-main/project-sub-1 文件夾是空的:
cd /path/to/tempgit clone https://github.com/username/project-main.git
如果希望子模塊代碼也獲取到,一種方式是在克隆主項目的時候帶上參數 --recurse-submodules,這樣會遞歸地將項目中所有子模塊的代碼拉取。
cd /path/to/temp2git clone https://github.com/username/project-main.git--recurse-submodules
此時 project-main/project-sub-1 文件夾是有內容的,并且固定在某個 Git 提交的版本上。
另外一種可行的方式是,在當前主項目中執行:
git submodule initgit submodule update
則會根據主項目的配置信息,拉取更新子模塊中的代碼。
3.子模塊內容的更新對于子模塊而言,并不需要知道引用自己的主項目的存在。對于自身來講,子模塊就是一個完整的 Git 倉庫,按照正常的 Git 代碼管理規范操作即可。
對于主項目而言,子模塊的內容發生變動時,通常有三種情況:
1)當前項目下子模塊文件夾內的內容發生了未跟蹤的內容變動;
2)當前項目下子模塊文件夾內的內容發生了版本變化;
3)當前項目下子模塊文件夾內的內容沒變,遠程有更新;
> 情況1:子模塊有未跟蹤的內容變動對于第1種情況,通常是在開發環境中,直接修改子模塊文件夾中的代碼導致的。
此時在主項目中使用 git status 能夠看到關于子模塊尚未暫存以備提交的變更,但是于主項目而言是無能為力的,使用 git add/commit 對其也不會產生影響。
? project-main git:(master) git status位于分支 master
您的分支與上游分支 'origin/master' 一致。
尚未暫存以備提交的變更:
(使用 "git add <文件>..." 更新要提交的內容)
(使用 "git checkout -- <文件>..." 丟棄工作區的改動)
(提交或丟棄子模組中未跟蹤或修改的內容)
修改: project-sub-1 (未跟蹤的內容)
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
在此情景下,通常需要進入子模塊文件夾,按照子模塊內部的版本控制體系提交代碼。
當提交完成后,主項目的狀態則進入了情況2,即當前項目下子模塊文件夾內的內容發生了版本變化。
> 情況2:子模塊有版本變化當子模塊版本變化時,在主項目中使用 git status 查看倉庫狀態時,會顯示子模塊有新的提交:
? project-main git:(master) ? git status位于分支 master
您的分支與上游分支 'origin/master' 一致。
尚未暫存以備提交的變更:
(使用 "git add <文件>..." 更新要提交的內容)
(使用 "git checkout -- <文件>..." 丟棄工作區的改動)
修改: project-sub-1 (新提交)
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
在這種情況下,可以使用 git add/commit 將其添加到主項目的代碼提交中,實際的改動就是那個子模塊 文件 所表示的版本信息:
git diff HEAD HEAD^diff --git a/project-sub-1 b/project-sub-1
index ace9770..7097c48 160000
--- a/project-sub-1
+++ b/project-sub-1
@@ -1 +1 @@
-Subproject commit ace977071f94f4f88935f9bb9a33ac0f8b4ba935
+Subproject commit 7097c4887798b71cee360e99815f7dbd1aa17eb4
通常當子項目更新后,主項目修改其所依賴的版本時,會產生類似這種情景的 commit 提交信息。
> 情況3:子模塊遠程有更新通常來講,主項目與子模塊的開發不會恰好是同時進行的。通常是子模塊負責維護自己的版本升級后,推送到遠程倉庫,并告知主項目可以更新對子模塊的版本依賴。
在這種情況下,主項目是比較茫然的。
之前曾經提到,主項目可以使用 git submodule update 更新子模塊的代碼,但那是指 當前主項目文件夾下的子模塊目錄內容 與 當前主項目記錄的子模塊版本 不一致時,會參考后者進行更新。
但如今這種情況下,后者 當前主項目記錄的子模塊版本 還沒有變化,在主項目看來當前情況一切正常。
此時,需要讓主項目主動進入子模塊拉取新版代碼,進行升級操作。
通常流程是:
cd project-sub-1git pull origin master
子模塊目錄下的代碼版本會發生變化,轉到情況2的流程進行主項目的提交。
當主項目的子項目特別多時,可能會不太方便,此時可以使用 git submodule 的一個命令 foreach 執行:
git submodule foreach 'git pull origin master'> 情況匯總終上所述,可知在不同場景下子模塊的更新方式如下:
- 對于子模塊,只需要管理好自己的版本,并推送到遠程分支即可;
 - 對于父模塊,若子模塊版本信息未提交,需要更新子模塊目錄下的代碼,并執行 commit 操作提交子模塊版本信息;
 - 對于父模塊,若子模塊版本信息已提交,需要使用 git submodule update ,Git 會自動根據子模塊版本信息更新所有子模塊目錄的相關代碼。
 
網上流傳了一些偏法,主要步驟是直接移除模塊,并手動修改 .gitmodules、.git/config 和 .git/modules 內容。包含了一大堆類似git rm --cached <sub-module>、rm -rf <sub-moduel>、rm .gitmodules 和 git rm --cached 之類的代碼。
實際上這是一種比較野的做法,不建議使用。
根據官方文檔的說明,應該使用 git submodule deinit 命令卸載一個子模塊。這個命令如果添加上參數 --force,則子模塊工作區內即使有本地的修改,也會被移除。
git submodule deinit project-sub-1git rm project-sub-1
執行 git submodule deinit project-sub-1 命令的實際效果,是自動在 .git/config 中刪除了以下內容:
[submodule "project-sub-1"]url = https://github.com/username/project-sub-1.git
執行 git rm project-sub-1 的效果,是移除了 project-sub-1 文件夾,并自動在 .gitmodules 中刪除了以下內容:
[submodule "project-sub-1"]path = project-sub-1
url = https://github.com/username/project-sub-1.git
此時,主項目中關于子模塊的信息基本已經刪除(雖然貌似 .git/modules 目錄下還有殘余):
? project-main git:(master) ? gs位于分支 master
您的分支與上游分支 'origin/master' 一致。
要提交的變更:
(使用 "git reset HEAD <文件>..." 以取消暫存)
修改: .gitmodules
刪除: project-sub-1
可以提交代碼:
git commit -m "delete submodule project-sub-1"至此完成對子模塊的刪除。
總結
當項目比較復雜,部分代碼希望獨立為子模塊進行版本控制時,可以使用 git submodule 功能。
使用 git submodule 功能時,主項目倉庫并不會包含子模塊的文件,只會保留一份子模塊的配置信息及版本信息,作為主項目版本管理的一部分。
本篇文章簡單介紹了 git submodule 的添加和刪除,以及項目開發過程中主項目與子模塊不同狀態時刻的操作方式。
總結
以上是生活随笔為你收集整理的使用qtcreator中的git_Git中submodule的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 移动app测试的多样性_app移动端接口
 - 下一篇: key位置 win10生成的ssh_华为