使用Git Submodule可能遇到的坑
前言
對(duì)于一些比較大的工程,為了便于復(fù)用,常常需要抽取子項(xiàng)目。例如我開(kāi)發(fā)的猿題庫(kù)客戶(hù)端現(xiàn)在包括3門(mén)考試,客戶(hù)端涉及的公共UI、公共底層邏輯、公共的第三方庫(kù)、以及公共的答題卡掃描算法就被我分別抽取成了子項(xiàng)目。這些子項(xiàng)目都以git submodule的形式,增加到工程中。
在使用了git submodule一段時(shí)間后,我發(fā)現(xiàn)了一些submodule的問(wèn)題,在此分享給大家。
更新submodule的坑
submodule項(xiàng)目和它的父項(xiàng)目本質(zhì)上是2個(gè)獨(dú)立的git倉(cāng)庫(kù)。只是父項(xiàng)目存儲(chǔ)了它依賴(lài)的submodule項(xiàng)目的版本號(hào)信息而已。如果你的同事更新了submodule,然后更新了父項(xiàng)目中依賴(lài)的版本號(hào)。你需要在git pull之后,調(diào)用 git submodule update來(lái)更新submodule信息。
這兒的坑在于,如果你git pull之后,忘記了調(diào)用 git submodule update,那么你極有可能再次把舊的submodule依賴(lài)信息提交上去。對(duì)于那些習(xí)慣使用 git commit -a的人來(lái)說(shuō),這種危險(xiǎn)會(huì)更大一些。所以建議大家:
1.git pull之后,立即執(zhí)行g(shù)it status, 如果發(fā)現(xiàn)submodule有修改,立即執(zhí)行g(shù)it submodule update
2.盡量不要使用 git commit -a, git add命令存在的意義就是讓你對(duì)加入暫存區(qū)的文件做二次確認(rèn),而 git commit -a相當(dāng)于跳過(guò)了這個(gè)確認(rèn)過(guò)程。
更復(fù)雜一些,如果你的submodule又依賴(lài)了submodule,那么很可能你需要在git pull 和 git submodule update之后,再分別到每個(gè)submodule中再執(zhí)行一次git submodule update,這里可以使用 git submodule foreach命令來(lái)實(shí)現(xiàn): git submodule foreach git submodule update
修改submodule的坑
有些時(shí)候你需要對(duì)submodule做一些修改,很常見(jiàn)的做法就是切到submodule的目錄,然后做修改,然后commit和push。
這里的坑在于,默認(rèn)git submodule update并不會(huì)將submodule切到任何branch,所以,默認(rèn)下submodule的HEAD是處于游離狀態(tài)的(‘detached HEAD’ state)。所以在修改前,記得一定要用git checkout master將當(dāng)前的submodule分支切換到master,然后才能做修改和提交。
如果你不慎忘記切換到master分支,又做了提交,可以用cherry-pick命令挽救。具體做法如下:
1.用 git checkout master 將HEAD從游離狀態(tài)切換到 master 分支, 這時(shí)候,git會(huì)報(bào)Warning說(shuō)有一個(gè)提交沒(méi)有在branch上,記住這個(gè)提交的change-id(假如change-id為 aaaa)
2.用 git cherry-pick aaaa 來(lái)將剛剛的提交作用在master分支上
3.用 git push 將更新提交到遠(yuǎn)程版本庫(kù)中
以下是相關(guān)命令的操作示范和命令行輸出結(jié)果:
1. ui_common git:(df697f9) git checkout master
2.Warning: you are leaving 1 commit behind, not connected to
3.any of your branches:
4.
5. df697f9 forget to check out master
6.
7.If you want to keep them by creating a new branch, this may be a good time
8.to do so with:
9.
10. git branch new_branch_name df697f911e5a0f09d883f8f360977e470c53d81e
11.
12.Switched to branch 'master'
13. ui_common git:(master) git cherry-pick df697f9
使用第三方工具
對(duì)于submodule的重度使用者,有幾個(gè)工具可作推薦:
1.Repo Google用于管理Android項(xiàng)目的工具。
2.Gitslave
3.Git Subtree
以上工具,我都沒(méi)有實(shí)際用過(guò),所以無(wú)法提供更多信息。
Tips
由于常常使用submodule的相關(guān)命令,可以在 ~/.gitconfig文件中將其設(shè)置別名,方便操作,我設(shè)置的所有相關(guān)別名如下:
1.[alias]
2. st = status -s
3. ci = commit
4. l = log --oneline --decorate -12 --color
5. ll = log --oneline --decorate --color
6. lc = log --graph --color
7. co = checkout
8. br = branch
9. rb = rebase
10. dci = dcommit
11. sbi = submodule init
12. sbu = submodule update
13. sbp = submodule foreach git pull
14. sbc = submodule foreach git co master
參考鏈接
1.《why-your-company-shouldnt-use-git-submodules》 (需翻墻)
來(lái)源:唐巧的技術(shù)博客