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