背景
項目A與項目B存在公用模塊讼昆,在項目A中修改Bug或增加新功能需要同步到項目B中,由于存在區(qū)別所以還不能完全copy
需求分析
- 公用代碼遷移出去獨立的 git 倉庫,供其他項目共享代碼
- 公用代碼原本是什么樣,抽取后也是什么樣,不像pod會對公用代碼進(jìn)行動態(tài)庫或靜態(tài)庫的包裝
- 公用代碼庫是可以在不同項目間雙向同步的而不是單向同步
- 保留公用代碼庫的歷史提交記錄與雙向同步記錄
雙向同步的栗子:A項目中依賴了子項目B岩齿,最方便的方式自然是直接在A項目里改B子項目對應(yīng)的目錄里的代碼,然后測試通過后苞俘,直接提交代碼盹沈,這個更改也提交到B子項目的 Git倉庫里。同時子項目B也可以單獨提交到 Git 倉庫,再在A項目里把子項目B的代碼update乞封。
現(xiàn)有方案
- Git Submodule:這是Git官方以前的推薦方案
- Git Subtree:從 Git 1.5.2 開始做裙,Git 新增并推薦使用這個功能來管理子項目
- npm:node package manager,實際上不僅僅是 node 的包管理工具
- composer:暫且認(rèn)為他是php版npm
雖然 npm肃晚,composer锚贱,maven 等更側(cè)重于包的依賴管理,以上幾個方案都是能夠做到在不同項目中同步同一塊代碼的关串,但沒法雙向同步拧廊,更適用于子項目代碼比較穩(wěn)定的情形。Git Submodule 和 Git Subtree 都是官方支持的功能晋修,不具有依賴管理的功能吧碾,但能滿足我們的要求。Git Subtree相對來說會更好一些 墓卦。
submodule 與 subtree對比
-
git submodule
- 允許其他的倉庫指定以一個commit嵌入倉庫的子目錄
- 倉庫
clone
下來需要init
和update
- 會產(chǎn)
.gitmodule
文件記錄 submodule 版本信息 - git submodule 刪除起來比較費勁
-
git subtree
- 避免以上問題
- 管理和更新流程比較方便
- git subtree合并子倉庫到項目中的子目錄倦春。不用像submodule那樣每次子項目修改了后要
init
和update
。萬一哪次沒update就直接add .
將.gitmodule
也commit
上去就悲劇了 - git v1.5.2以后建議使用git subtree
實施步驟
假設(shè)P1項目落剪、P2項目共用S項目
1. 關(guān)聯(lián)Subtree
'' cd P1項目的路徑
'' git subtree add --prefix=<S項目的相對路徑> <S項目git地址> <分支> --squash
解釋:--squash意思是把subtree的改動合并成一次commit睁本,這樣就不用拉取子項目完整的歷史記錄。--prefix之后的=等號也可以用空格忠怖。
2. 更新代碼
P1呢堰、P2項目里各種提交commit,其中有些commit會涉及到S目錄的更改凡泣,但是沒關(guān)系
3. 提交更改到子項目
'' cd P1項目的路徑
'' git subtree push --prefix=<S項目的相對路徑> <S項目git地址> <分支>
Git 會遍歷步驟2中所有的commit暮胧,從中找出針對S目錄的更改,然后把這些更改記錄提交到S項目的Git服務(wù)器上问麸,并保留步驟2中的相關(guān)S的提交記錄到S倉庫中
4. 更新子目錄
''cd P2項目的路徑
''git subtree pull --prefix=<S項目的相對路徑> <S項目git地址> <分支> --squash
拆分已有項目
需要從現(xiàn)有項目中抽取公共模塊單獨進(jìn)行g(shù)it管理
假設(shè)已有項目P抽取項目S
1. 提交日志分離
''cd P項目的路徑
''git subtree split -P <S項目的相對路徑> -b <臨時branch>
Git 會遍歷所有的commit,分離出與S項目的相對路徑相關(guān)的commit钞翔,并存入臨時branch中
2. 創(chuàng)建子repo
''mkdir <S項目新路徑>
''cd S項目新路徑
''git init
''git pull <P項目的路徑> <臨時branch>
''git remote add origin <S項目的git倉庫>
''git push origin -u master
3. 清理數(shù)據(jù)
''cd P項目的路徑
''git rm -rf <S項目的相對路徑>
''git commit -m '移除相應(yīng)模塊' # 提交刪除申請
''git branch -D <臨時branch> # 刪除臨時分支
4. 添加subtree
''git subtree add --prefix=<S項目的相對路徑> <S項目git地址> <分支> --squash
''git push origin master
執(zhí)行完第2步時严卖,對應(yīng)的目錄已經(jīng)剝離出來形成獨立的項目了。第3布轿,4步主要是把當(dāng)前項目的對應(yīng)的文件給刪除哮笆,重新在P項目建立Subtree
Tips
- 相對路徑區(qū)別大小寫