使用GIT SUBTREE集成項目到子目錄
使用場景
例如,在項目Game中有一個子目錄AI。Game和AI分別是一個獨立的git項目,可以分開維護。為了避免直接復制粘貼代碼,我們希望Game中的AI子目錄與AI的git項目關聯(lián),有3層意思:
AI子目錄使用AI的git項目來填充,內容保持一致。
當AI的git項目代碼有更新,可以拉取更新到Game項目的AI子目錄來。
反過來,當Game項目的AI子目錄有變更,還可以推送這些變更到AI的git項目。用git subtree可以輕松滿足上面的需求。
對比git submodule
如果你沒有用過git submodule,你甚至可以不用了解git submodule是什么,submodule的基本介紹也不在本文的說明范圍內。雖然它滿足了上述差不多的需求,但是復雜難用,以至于需要這么長一篇教程才能說清楚用法。
如果你的項目正在使用git submodule,你應該知道用submodule有多么麻煩,這里還有一篇文章專門解釋git submodule的缺點,可以參考前面教程里的最后一段來刪除submodule(是的,連刪除步驟都非常麻煩)。
使用git subtree之后,管理、更新都更加方便。
什么是git subtree
git subtree是一條git子命令,本質上subtree是一種合并策略,從git v1.5.2,官方就推薦使用subtree代替submodule,所以它并不需要保存.submodule這樣的元信息。
git subtree的前提條件
subtree子命令很晚才集成到git中,請確保你的git版本(使用git --version查看) > v1.8.0.0。有些文章中說v1.7.11就已經集成了,實際上沒有,如果直接執(zhí)行會看到這樣的結果:
$git subtree
git: 'subtree' is not a git command. See 'git --help'.
如果你是在OS X下使用git,推薦用homebrew來安裝新版本
$brew install git
$git --version git version 1.8.3.4
git subtree用法
針對第一段的3條需求,我分別說明具體的命令。
1. 第一次添加子目錄,建立與git項目的關聯(lián)
建立關聯(lián)總共有2條命令。
語法:git remote add -f <子倉庫名> <子倉庫地址>
解釋:其中-f意思是在添加遠程倉庫之后,立即執(zhí)行fetch。
語法:git subtree add --prefix=<子目錄名> <子倉庫名> <分支> --squash
解釋:--squash意思是把subtree的改動合并成一次commit,這樣就不用拉取子項目完整的歷史記錄。--prefix之后的=等號也可以用空格。
示例
$git remote add -f ai https://github.com/aoxu/ai.git
$git subtree add --prefix=ai ai master --squash
2. 從遠程倉庫更新子目錄
更新子目錄有2條命令。
語法:git fetch <遠程倉庫名> <分支>
語法:git subtree pull --prefix=<子目錄名> <遠程分支> <分支> --squash
示例
$git fetch ai master
$git subtree pull --prefix=ai ai --squash
3. 從子目錄push到遠程倉庫(確認你有寫權限)
推送子目錄的變更有1條命令。
語法:git subtree push --prefix=<子目錄名> <遠程分支名> 分支
示例
$git subtree push --prefix=ai ai master