Better Practice in Git Submodule

(文中提到的倉庫特指git倉庫)

1. 背景介紹

開發(fā)中可能會遇到這樣的情況:

  • 項目依賴一個library
  • 這個library在多個項目中都要用到(符合封裝復用的原則)
  • 我需要根據需求修改library的內容
  • 不同項目依賴的library可能是不同版本

如果把library的文件直接放在當前項目的倉庫中暴凑,會導致一個問題:不同項目同步library的更新會變成一場災難(耗費大量時間且易出錯)晦譬。

于是,submodule 誕生了:

submodule提供了一種能力:在一個倉庫中娩井,允許以“子目錄”的形式存放另一個倉庫鳖昌,同時兩個倉庫獨立提交。

(“子目錄”打引號是因為并不是真正的子目錄)

回到上面的需求:

  • library作為單獨的倉庫以submodule的形式引入到不同的項目中
  • 一個項目更新了library,其他項目可以方便地更新
  • 不同的項目可以方便地維護不同的library版本

...

2. 各個場景的用法

2.1 給倉庫添加submodule

git submodule add url moduleName
添加submodule

2.2 clone一個有submodule的倉庫

2.2.1常規(guī)操作

如果clone的倉庫有submodule缅刽,是不能直接使用的读跷,需要運行以下兩條命令來初始化梗搅。

git submodule init
git submodule update
初始化有submodule的倉庫

2.2.2 submodule中嵌套了submodule

上面的操作不會初始化嵌套的submodule,如果遇到嵌套的情況效览,你當然可以cd到對應目錄无切,再次執(zhí)行git submodule init和git submodule update,還有一個便捷操作:

git submodule update --init --recursive

2.3 更新遠程submodule

submodule會經常更新丐枉, update 是submodule非常重要的操作哆键,它的作用是:

Update the registered submodules to match what the superproject expects by cloning missing submodules, fetching missing commits in submodules and updating the working tree of the submodules.

可見,根據命令的參數瘦锹,update的功能非常豐富:

  • clone本地缺失的submodule
  • fetch(submodule中)本地缺失的commits
  • 更新工作空間(就是當前目錄中看到的代碼)

更新遠程submodule的基礎操作是

git submodule update --remote

以下是各種場景的用法

2.3.1 遠程添加了新的submodule

git submodule update --init --remote

2.3.2 遠程submodule有更新籍嘹,本地沒更新

git submodule update --remote

2.3.3 遠程submodule有更新,本地也有更新

現在是這篇文章最重要的部分弯院,因為這個場景是submodule常見場景中最讓人困惑的辱士,如果你直接按照上面的操作(git submodule update --remote), 會發(fā)現本地的提交不見了。

想要解決這個問題听绳,就要知道git submodule update --remote到底做了什么:

  • 對于每一個submodule, git 會fetch其遠程master分支(*可配置)的最新commit颂碘。
  • 拉取到新的commit后,checkout到最新的commit(此時HEAD指針未指向任何分支椅挣,即submodule處于游離狀態(tài)-detached)

綜上头岔,默認狀態(tài)下,所有的submodule都處于游離狀態(tài), 新增本地提交后也是游離狀態(tài)贴妻,這時執(zhí)行git submodule update --remote切油,submodule被checkout到遠程master分支(*可配置)最新的commit, 于是本地的提交從工作空間中消失了(如下圖)。

常見問題之: 游離狀態(tài)

了解到原因名惩,就知道如何解決更新submodule時的游離問題以及本地修改丟失的問題

(1) 給submodule 切分支
cd到submodule的目錄下澎胡,手動checkout到具體的分支下
(2) update時添加 --merge或--rebase
git submodule update --remote --merge
正確操作
Tip1: 關于配置submodule的分支

操作git submodule update --remote fetch的分支是可以配置的(默認是master),配置方式是:

git config .gitmodules submodule.<submoduleName>.branch <branch>

也可以改直接改.gitmodules這個配置文件

# in file .gitmodules
[submodule "module/D"]
    path = module/D
    url = git@xxx.git
    branch = test//改成對應的分支名 
Tip2: 別慌娩鹉,你的東西丟不了

剛接觸submodule的時候攻谁,很多朋友看到自己的本地提交丟失就慌了,因為各個記錄中好像都找不到剛才的內容弯予。這里介紹一個利器: reflog(顧名思義: ref的log戚宦,因為git中的HEAD以及分支都是ref指針,我們通過插件HEAD的log就能知道剛剛“丟失”的commit)

# cd to submodule directory
git reflog HEAD
reflog 示例

3. 一些好用的設置項

3.1 push倉庫時锈嫩,確保修改的submodule已經push

團隊協(xié)作時受楼,有一種很常見的錯誤垦搬,自己提交倉庫時,忘了提交submodule的commit艳汽,導致同事無法更新到submodule最新的內容(因為它只在你的本地倉庫)猴贰。為了避免這種錯誤,可以在push時添加git push --recurse-submodules=check幫助檢查:

git push --recurse-submodules=check

或者修改配置河狐,一勞永逸米绕。

git config push.recurseSubmodules check

3.2 更好看的設置項

默認的設置項,看不到submodule修改的內容馋艺,可以修改配置:

git config status.submodulesummary 1
更友好的status

3.3 這些命令也太長了吧

上文中最重要的命令應該是git submodule update --remote了栅干,本來就挺長的,在加一個--merge--rebase就更長了捐祠,這也太長了吧碱鳞,手都敲酸了。雏赦。劫笙。別急芙扎,git alias(git別名機制)來了:

git config alias.supdate 'submodule update --remote --merge'

這樣設置后就可以用git supdate代替git submodule update --remote --merge操作了星岗。

4. 一些需要注意的東西

4.1 對于模型的理解

  • 雖然工作空間中看到的submodule是一個個子目錄,但submodule不是以子目錄的形式存放在主倉庫中的(這也是前文“子目錄”加引號的原因)戒洼,這一點比較違反直覺俏橘。
  • 在底層的存儲上,所有的submodule也是存在主倉庫的.git目錄中圈浇。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末寥掐,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子磷蜀,更是在濱河造成了極大的恐慌召耘,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件褐隆,死亡現場離奇詭異污它,居然都是意外死亡,警方通過查閱死者的電腦和手機庶弃,發(fā)現死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門衫贬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人歇攻,你說我怎么就攤上這事固惯。” “怎么了缴守?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵葬毫,是天一觀的道長镇辉。 經常有香客問我,道長贴捡,這世上最難降的妖魔是什么摊聋? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮栈暇,結果婚禮上麻裁,老公的妹妹穿的比我還像新娘。我一直安慰自己源祈,他們只是感情好煎源,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著香缺,像睡著了一般手销。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上图张,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天锋拖,我揣著相機與錄音,去河邊找鬼祸轮。 笑死兽埃,一個胖子當著我的面吹牛,可吹牛的內容都是我干的适袜。 我是一名探鬼主播柄错,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼苦酱!你這毒婦竟也來了售貌?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤疫萤,失蹤者是張志新(化名)和其女友劉穎颂跨,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體扯饶,經...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡恒削,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了帝际。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蔓同。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蹲诀,靈堂內的尸體忽然破棺而出斑粱,到底是詐尸還是另有隱情,我是刑警寧澤脯爪,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布则北,位于F島的核電站矿微,受9級特大地震影響,放射性物質發(fā)生泄漏尚揣。R本人自食惡果不足惜涌矢,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望快骗。 院中可真熱鬧娜庇,春花似錦、人聲如沸方篮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽藕溅。三九已至匕得,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間巾表,已是汗流浹背汁掠。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留集币,地道東北人考阱。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像惠猿,于是被迫代替她去往敵國和親羔砾。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內容

  • Add & Commit git init 初始化一個 Git 倉庫(repository)偶妖,即把當前所在目錄變成...
    冬絮閱讀 4,793評論 0 8
  • git教程 git簡介 git是一個開源的分布式版本控制系統(tǒng),用于敏捷高效的處理任何大小的項目政溃。 git工作流程相...
    阿貍404閱讀 276評論 0 0
  • 對于一個新的包括submodule的項目調用以下命令即可 或者 配置 首先是配置帳號信息 ssh -T git@g...
    brownfeng閱讀 467評論 0 0
  • 分布式版本管理工具 git屬于分布式 svn集中式 git安裝 git初始化一個倉庫 其實就是創(chuàng)建了一個.git隱...
    SnowDragonYY閱讀 1,501評論 0 0
  • Git Tools - Submodules 1. 應用場景 需求 當你在一個項目 project1 上工作時趾访,你...
    最好時光萌萌噠閱讀 509評論 1 2