Git 進(jìn)階 - 子倉(cāng)庫(kù) subtree

學(xué)習(xí)背景

問(wèn)題實(shí)例(真實(shí)訴求)

一個(gè)工具類庫(kù),有以下兩個(gè)目標(biāo):

  • 不與業(yè)務(wù)相關(guān),便于復(fù)用
    • 方案:maven 作為依賴引用,使用方便,但更新繁瑣
      • 優(yōu)點(diǎn):使用方便
      • 缺點(diǎn):1. 不易更新,發(fā)現(xiàn)工具類不符合需求時(shí),直接要更改源倉(cāng)庫(kù)處理,update 使用;2.gradle 引用后,在沒(méi)有 download 源碼的情況下,看不到注釋,注釋對(duì)于一個(gè)工具類還是很重要的
  • 需要快速迭代更新
    • 方案:直接引用 lib 源碼,更新便捷實(shí)時(shí),但不適合多項(xiàng)目的使用

如果直接使用 Git 管理這個(gè)lib 添加到這個(gè)項(xiàng)目來(lái)呢,單獨(dú)維護(hù)??赡芫蜁?huì)出現(xiàn)每一次更新 repo 就要更新多個(gè) repo 的情況。對(duì)于有很多開(kāi)發(fā)協(xié)同者來(lái)說(shuō),簡(jiǎn)直是災(zāi)難。

git subtree 是什么?

git subtree 可以實(shí)現(xiàn)一個(gè)倉(cāng)庫(kù)作為其他倉(cāng)庫(kù)的子倉(cāng)庫(kù),能夠相對(duì)較好的解決上面兩難問(wèn)題。

subtree

有個(gè)和 git subtree 概念類似的功能 git submodule,雖然都沒(méi)有用過(guò),但目前來(lái)看 git subtreegit submodule 更加強(qiáng)大,是可以替代 submodule 的方案。

  • git submodule 在本地可能存在多個(gè) git 代碼倉(cāng)庫(kù)
  • git subtree 只有一個(gè)代碼庫(kù),也就是說(shuō)在項(xiàng)目?jī)?nèi)部依賴外部獨(dú)立項(xiàng)目的時(shí)候,是完全無(wú)感知的操作。

subtree 的作用就是可以實(shí)現(xiàn)一個(gè)倉(cāng)庫(kù)作為其他倉(cāng)庫(kù)的子倉(cāng)庫(kù),對(duì)于主項(xiàng)目來(lái)說(shuō),另一個(gè)項(xiàng)目只作為主項(xiàng)目的一個(gè)子目錄而存在。

圖片來(lái)自 :https://segmentfault.com/a/1190000012002151

使用

$ git subtree -h    
usage: git subtree add   --prefix=<prefix> <commit>
   or: git subtree add   --prefix=<prefix> <repository> <ref>
   or: git subtree merge --prefix=<prefix> <commit>
   or: git subtree pull  --prefix=<prefix> <repository> <ref>
   or: git subtree push  --prefix=<prefix> <repository> <ref>
   or: git subtree split --prefix=<prefix> <commit>

    -h, --help            show the help
    -q                    quiet
    -d                    show debug messages
    -P, --prefix ...      the name of the subdir to split out
    -m, --message ...     use the given message as the commit message for the merge commit

options for 'split'
    --annotate ...        add a prefix to commit message of new commits
    -b, --branch ...      create a new branch from the split subtree
    --ignore-joins        ignore prior --rejoin commits
    --onto ...            try connecting new tree to an existing one
    --rejoin              merge the new branch back into HEAD

options for 'add', 'merge', and 'pull'
    --squash              merge subtree changes as a single commit

在主項(xiàng)目中添加子項(xiàng)目

創(chuàng)建一個(gè)git repo GitStudy

創(chuàng)建一個(gè) lib repo commonToolsCopy

使用 subtree 命令,將 tools 放到 gitStudy 目錄下(作為lib)

下面 commonTools

$ git subtree add --prefix=commonTools http://git.ninebot.cn:8888/tingtingtina/commontoolscopy.git master --squash
  • --squash 參數(shù)表示不拉取歷史信息,而只生成一條 commit 信息。

  • = 后面的 commonTools 是子項(xiàng)目 clone 后在本地的目錄名,可以是多級(jí),比如 lib/xxx

  • master 指的是子項(xiàng)目的分支名

上面命令執(zhí)行后,就可以將 commonTools 倉(cāng)庫(kù)中 master 上的更新更新到本地

$ git subtree add --prefix=commonTools http://git.ninebot.cn:8888/tingtingtina/commontoolscopy.git master --squash
git fetch http://git.ninebot.cn:8888/tingtingtina/commontoolscopy.git master
warning: no common commits
remote: Enumerating objects: 242, done.
remote: Counting objects: 100% (242/242), done.
remote: Compressing objects: 100% (99/99), done.
remote: Total 242 (delta 44), reused 242 (delta 44)
Receiving objects: 100% (242/242), 51.03 KiB | 4.25 MiB/s, done.
Resolving deltas: 100% (44/44), done.
From http://git.ninebot.cn:8888/tingtingtina/commontoolscopy
 * branch            master     -> FETCH_HEAD
Added dir 'commonTools'

之后會(huì)生成兩條日志信息

$ git log
commit a0a743a92c1fc6eddc204abbcfbab0ac530d3c46 (HEAD -> master)
Merge: a8b13f3 23e60fb
Author: liting <xxlt0310@163.com>
Date:   Thu Apr 15 17:25:46 2021 +0800

    Merge commit '23e60fbfdaa2ce6e63b4cc666ed59cd373d33c1e' as 'commonTools'

commit 23e60fbfdaa2ce6e63b4cc666ed59cd373d33c1e
Author: liting <xxlt0310@163.com>
Date:   Thu Apr 15 17:25:46 2021 +0800

    Squashed 'commonTools/' content from commit d25f3bd
    
    git-subtree-dir: commonTools
    git-subtree-split: d25f3bd8f7ab886c8806f031a17d4a841671a21a

commit a8b13f3d1cba3c5402821d613b9e0ab29f028998 (origin/master)
Author: liting <xxlt0310@163.com>
Date:   Thu Apr 15 17:13:05 2021 +0800

    init

添加之后 commonTools 就是主項(xiàng)目的一個(gè)普通文件夾,如果這時(shí)候 commonTools 內(nèi)容更新之后,正常 git push 即可,子項(xiàng)目對(duì)于主項(xiàng)目來(lái)說(shuō)完全是透明的。

推送到子項(xiàng)目倉(cāng)庫(kù)

在主項(xiàng)目 git push 之后,對(duì)子項(xiàng)目修改的內(nèi)容是不會(huì)直接更新到子項(xiàng)目自身的

需要執(zhí)行 git subtree push

git subtree push --prefix=commonTools http://git.ninebot.cn:8888/tingtingtina/commontoolscopy.git master 

子項(xiàng)目倉(cāng)庫(kù)更新

如果單獨(dú)對(duì)子項(xiàng)目做了更新,主項(xiàng)目就需要手動(dòng)更新下了

$ git subtree pull --prefix=commonTools http://git.ninebot.cn:8888/tingtingtina/commontoolscopy.git master --squash

執(zhí)行之后,仍然會(huì)在主項(xiàng)目中生成相關(guān)的 commit 記錄

在 subtree 相關(guān)命令經(jīng)常會(huì)用到 <repository> 每次都寫(xiě)地址還是比較麻煩,這里可以用 git remote 命令簡(jiǎn)化寫(xiě)法,為這個(gè)遠(yuǎn)程地址定義一個(gè) “別名”

$ git remote add utils http://git.ninebot.cn:8888/tingtingtina/commontoolscopy.git

比如使用 subtree push 的時(shí)候就可以使用如下命令

$ git subtree push --prefix=commonTools utils master

移除子項(xiàng)目(切換子項(xiàng)目分支)

在添加 subtree 的時(shí)候是指定了分支的,如果要切換分支直接移除 subtree,重新加入子項(xiàng)目的分支

git rm <subtree>
git commit
git subtree add --prefix=<subtree> <repository_url> <subtree_branch>

驗(yàn)證1:其他人 clone 該項(xiàng)目對(duì) sub repo是無(wú)感知的

驗(yàn)證2:在主項(xiàng)目中修改 sub repo 的內(nèi)容 push,在 app 中會(huì)形成 commit 在 sub repo 中不會(huì)有 commit

驗(yàn)證3:使用一下命令,可以push 到 sub repo 中 推送修改到源倉(cāng)庫(kù)

git subtree push --prefix=commonTools http://git.ninebot.cn:8888/tingtingtina/commontoolscopy.git master 

驗(yàn)證4:直接在 sub repo 項(xiàng)目中更新內(nèi)容

那么 main repo 需要還是需要 pull 一下 從源倉(cāng)庫(kù)拉取更新

git subtree pull --prefix=commonTools http://git.ninebot.cn:8888/tingtingtina/commontoolscopy.git master --squash

非原理性提示 不加 --squash 不可以,

在 pull 的過(guò)程中可能需要處理沖突

驗(yàn)證5:修改的內(nèi)容同時(shí)包含主項(xiàng)目和子項(xiàng)目, 使用 git push 再使用 git subtree push 會(huì)做挑揀,但如果混雜的內(nèi)容很多的話,這個(gè)過(guò)程也會(huì)變得復(fù)雜,so 建議 盡可能分開(kāi)提交,減少這種沖突。

參考

https://segmentfault.com/a/1190000012002151
http://einverne.github.io/post/2020/04/git-subtree-usage.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 使用git subtree有一段時(shí)間了,主要用來(lái)解決多個(gè)項(xiàng)目共同使用相同代碼的同步問(wèn)題,特意簡(jiǎn)單整理了一下相關(guān)知識(shí)...
    Smileswlin閱讀 5,900評(píng)論 4 7
  • 背景 項(xiàng)目A與項(xiàng)目B存在公用模塊,在項(xiàng)目A中修改Bug或增加新功能需要同步到項(xiàng)目B中,由于存在區(qū)別所以還不能完全c...
    Archerlly閱讀 21,144評(píng)論 3 14
  • 本文首發(fā)在segmentfault中 背景 最近工作中遇到了一個(gè)問(wèn)題:隨著項(xiàng)目越來(lái)越多,很多項(xiàng)目依賴同一個(gè)模板或是...
    alv閱讀 8,013評(píng)論 1 5
  • 由于移動(dòng)互聯(lián)網(wǎng)的爆發(fā)以及響應(yīng)式頁(yè)面的尷尬癥,開(kāi)發(fā)web和mobile項(xiàng)目成為了標(biāo)配,當(dāng)然實(shí)際情況下,會(huì)有更多的項(xiàng)目...
    齊修_qixiuss閱讀 10,636評(píng)論 0 17
  • 使用GIT SUBTREE集成項(xiàng)目到子目錄 使用場(chǎng)景 例如,在項(xiàng)目Game中有一個(gè)子目錄AI。Game和AI分別是...
    anddygon閱讀 1,152評(píng)論 0 0

友情鏈接更多精彩內(nèi)容