git subtree用法
什麼時候需要 Subtree ?
1、當多個專案共用同一個模組程式碼,而這個模組程式碼跟著專案在快速更新的時候
2、把一部分程式碼遷移出去獨立為一個新的 git 倉庫,但又希望能夠保留這部分程式碼的歷史提交記錄。
git subtree的主要命令有:
$ git subtree add --prefix=<prefix> <commit>
$ git subtree add --prefix=<prefix> <repository> <ref>
$ git subtree pull --prefix=<prefix> <repository> <ref>
$ git subtree push --prefix=<prefix> <repository> <ref>
$ git subtree merge --prefix=<prefix> <commit>
$ git subtree split --prefix=<prefix> [OPTIONS] [<commit>]
git subtree用法
準備
我們先準備一個倉庫叫photoshop,一個倉庫叫libpng,然後我們希望把libpng作為photoshop的子倉庫。
photoshop的路徑為https://github.com/test/photoshop.git
photoshop
|
|-- photoshop.c
|-- photoshop.h
|-- main.c
\-- README.md
libPNG的路徑為https://github.com/test/libpng.git
,倉庫裡的檔案有:
libpng
|
|-- libpng.c
|-- libpng.h
\-- README.md
1. 第一次新增子目錄,建立與git專案的關聯(在父倉庫中新增子倉庫)
建立關聯總共有2條命令。
語法:git remote add -f <子倉庫名> <子倉庫地址>
解釋:其中-f意思是在新增遠端倉庫之後,立即執行fetch。
語法:git subtree add --prefix=<子目錄名> <子倉庫名> <分支> --squash
解釋:–squash意思是把subtree的改動合併成一次commit,這樣就不用拉取子專案完整的歷史記錄。–prefix之後的=等號也可以用空格。
示例:
$ git remote add -f libpng https://github.com/test/libpng.git
$ git subtree add --prefix=sub/libpng libpng master --squash
2. 從遠端倉庫更新子目錄
更新子目錄有2條命令。
語法:git fetch <遠端倉庫名> <分支>
語法:git subtree pull --prefix=<子目錄名> <遠端分支> <分支> --squash
示例:
$ git fetch libpng master
$ git subtree pull --prefix=sub/libpng https://github.com/test/libpng.git master --squash
3. 從子目錄push到遠端倉庫(確認你有寫許可權)
推送子目錄的變更有1條命令。
語法:git subtree push --prefix=<子目錄名> <遠端分支名> 分支
示例:
$ git subtree push --prefix=sub/libpng https://github.com/test/libpng.git master
4.git subtree split
每次執行 subtree 的 push 命令的時候,總會重新為子目錄生成新的提交。然而這造成了一些很麻煩的問題:
- 每個提交都需要重新計算,因此每次推送都需要把主倉庫所有的提交計算一遍,非常耗時;
- 每次 push 都是重新計算的,因此本地和遠端新倉庫的提交總是不一樣的,關鍵還沒有共同的父級,這導致 git 無法自動為我們解決衝突。
git subtree 提供了 split
命令就是為了解決這個問題
當使用了 split
命令後,git subtree 將確保對於相同歷史的分割始終是相同的提交號。
於是,當需要 push 的時候,git 將只計算 split 之後的新提交;並且下次 split 的時候,以前相同的歷史紀錄將得到相同的 git 提交號。
示例:
$ git subtree split --rejoin --prefix=sub/libpng --branch new_libpng
$ git push zenjs new_libpng:master
簡化git subtree命令
我們已經知道了git subtree 的命令的基本用法,但是上述幾個命令還是顯得有點複雜,特別是子倉庫的源倉庫地址,特別不方便記憶。
這裡我們把子倉庫的地址作為一個remote,方便記憶:
$ git remote add -f libpng https://github.com/test/libpng.git
然後可以這樣來使用git subtree命令:
$ git subtree add --prefix=sub/libpng libpng master --squash
$ git subtree pull --prefix=sub/libpng libpng master --squash
$ git subtree push --prefix=sub/libpng libpng master