Git - 子模塊


工作中會遇到這樣的問題,當你在一個項目上時,你需要在其中使用另外一個項目,這個項目也許是一個第三方開發的庫或者是你獨立開發 合並在多個項目中使用的。這樣就會產生一個問題:你想將兩個項目單獨處理但是又需要其中一個項目使用另一個。而Git通過子模塊處理這個問題,子模塊允許你將一個Git倉庫當做另一個Git倉庫的子目錄。允許你克隆另外一個倉庫到你的項目中並且保持你的提交相對對立。

開始使用子模塊

首先我們將一個已經存在的Git倉庫添加為正在工作的的倉庫的子模塊。運行git  submodule  add  <url>  命令添加子模塊。如果你想將它放在其他地方,可以通過在命令結尾添加路徑來實現。

模塊添加成功了,接下來我們看一下工作區的變化。運行 git  status 命令  

我們會發現多兩個新的文件,首先是.gitmodules文件。這個文件是一個配置文件,保存了項目URL和已經拉取的本地目錄之間的映射,查看一下里面的內容

可以看到文件里包含了上述的兩條內容,要重點注意的是,這個文件跟其他文件一樣是處在版本控制之下的,它會和該項目的其他文件一樣被拉取推送,這也是為什么克隆該項目的人知道去哪里獲得子模塊的原因。

這里要注意一點,因為.gitmodules文件中的URL是人們第一次克隆項目時的地址,因此我們需要盡可能的確保這個URL是可以被其他人訪問的。

接下來我們看看另一個新的文件,運行 git  diff  命令,

我們可以看到,雖然childModule1是工作目錄中的子目錄,但是Git會將它視作一個子模塊。當你不在那個目錄中時,Git並不會跟蹤他的內容,而是把它看做該倉庫的一個特殊提交。

當你將更改提交到版本庫時,我們會看到以下信息

 

注意childModule1記錄的160000模式。這是Git中的一種特殊模式,表示將一次提交記作一項目錄記錄的,而非將它記錄成一個子目錄或者一個文件。

除了自己添加子模塊,我們還可以克隆帶子模塊的目錄

克隆一個帶子模塊的項目

我們可以通過git  clone  <url> 來克隆一個帶子模塊的項目,在克隆這個項目時,默認會包含該子模塊的目錄,但是目錄里面沒有任何文件。克隆成功之后我們查看一下這個文件

childModule1文件目錄存在了,但是目錄是空的。這時我們需要運行兩個命令:第一個 git  submodule  init  用來初始化本地配置文件

 

第二個命令 git  submodule  update  用來拉取childModule1目錄的所有數據並檢出你上層項目里所列的合適的提交

到這里我們第一個克隆 包含子模塊項目的方法就到這了。既然說了有第一個,當然就有第二個了,第二個方法更簡單一點,直接一步到位,就是給 git  clone 命令加一個--recursive 參數,他就會自動初始化並更新倉庫的每一個子模塊

子模塊克隆好之后(不管是用那種方法克隆)我們看一下它的狀態,

可以看到的是非常醒目的一串紅色的字母,那這一串字母代表獲得一個游離的HEAD,這意味着HEAD指向的只是一次提交。那會這樣的原因是因為我們克隆項目的時候,Git將會獲得這些改動並更新子目錄的文件,但是會將子模塊留在一個叫做“游離的HEAD”的狀態,這也意味着子模塊沒有本地工作分支跟蹤改動。所以我們的做的任何改動都不會被跟蹤。

現在子模塊克隆好了,子目錄也處於我們先前提交的狀態了。

如果另外的一個開發者更改了子目錄的代碼,並作了提交,然后我們拉取那次引用合並,然后查看一下主目錄的狀態。

 git  merge  origin/master   命令的作用是將上游分支合並到本地

因為我們合並的僅僅只是只想子模塊的指針,但是它並不更新子模塊的代碼,所以主目錄的工作狀態處於一個臨時的狀態

然后我們再查看一下工作區和版本庫的區別

 會發現,我們所擁有的指向子模塊的指針和子模塊目錄的真實狀態並不匹配。所以為了修復這一點我們要再次執行 git  submodule update 命令

執行之后再次查看工作區和版本庫的區別我們會發現沒有區別了。

有一個很不方便的地方就是我們每次從主項目中拉去子模塊的變更都要這樣做。

子模塊的問題

使用子模塊並非沒有任何缺點。首先,你在子模塊目錄中工作時必須相對小心。當你運行git submodule update,它會檢出項目的指定版本,但是不在分支內。這叫做獲得一個分離的頭——這意味着 HEAD 文件直接指向一次提交,而不是一個符號引用。問題在於你通常並不想在一個分離的頭的環境下工作,因為太容易丟失變更了。如果你先執行了一次submodule update,然后在那個子模塊目錄里不創建分支就進行提交,然后再次從上層項目里運行git submodule update同時不進行提交,Git會毫無提示地覆蓋你的變更。技術上講你不會丟失工作,但是你將失去指向它的分支,因此會很難取到。

 

為了避免這個問題,當你在子模塊目錄里工作時應使用git checkout -b work創建一個分支。當你再次在子模塊里更新的時候,它仍然會覆蓋你的工作,但是至少你擁有一個可以回溯的指針。
 
參考文章:Git-子模塊
       Git工具-子模塊

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM