2020年2月14日 星期五

git submodule/subtree

※submodule

一、新增子模組

git submodule status // 只能看有沒有子模組,沒有什麼都不顯示;有就顯示 hash,此 hash 同子模組

git submodule add 路徑
有4個地方會改變
1.整個子模組會成為主模組的一個目錄
2.多了 .gitmodules(隱藏檔),裡面是多個子模組的資訊
3. .git 會增加 modules 資料夾,裡面是各個子模組,再點進去是子模組的 .git 目錄
4. .git/config 檔也會增加資訊,使用 git config --list 會抓此檔的資訊,所以
用這個命令也可以看到

注意事項:
1.主模組和子模組操作是分開的(主模組的命令只對自己有用,子模組也是),但在主模組可看到子模組的狀態,只能看有沒有變動,至於變動什麼要進去子模組操作才知道
  P.S 操作子模組要進去這個子模組裡面,命令都和之前一樣
2.子模組有變動,要做到 commit 這一步,主模組的 add 才有用,add 有用才能對子模組進行版本控制
3.如果只 push 主模組,那別人更新時會有麻煩,所以在 push 時,可用 git push --recurse-submodules=check
如果子模組沒有 push,就會報錯
git push --recurse-submodules=on-demand 會在主模組 push 前將子模組先 push,當然如果有錯就不行


如果有多個子模組都想更新,用上面的方法會進入各個子模組進行操作,比較麻煩,可用如下方式解決
git submodule update --remote 子模組名(如果要更新全部的模組就不需要打子模組名)
這樣所有的子模組就會更新了,但會使子模組分支變成 detached,
解決方法是在子模組新增一個分支,然後在 main 分支 merge 新的分支,最後再刪除新分支

上面的做法太麻煩,以下其中一個指令可以直接做好
git submodule update --remote --merge
git submodule update --remote --rebase


二、clone 有子模組的 git

clone 完,.gitmodules 檔案是 ok 的,但子模組裡是空的
git submodule status 看起來是有的,但實際上是空的

所以要下如下的指令
git submodule init // .git/config 會寫入子模組的資訊,但子模組仍然是空的
git submodule update // 下載子模組的資料
  P.S 以上兩行順序不能換,否則 update 也不報錯,但什麼都沒發生
git submodule update --init // 合併成一行

如果一開始就知道有子模組,可下如下的指令
git clone --recursive 路徑


三、刪除子模組

1.git submodule deinit submodule名(遠端的名字)或者 --all // 將 config 檔案裡的資訊移除,也會將子模組裡的東西清空,在做這步之前 status 必需要是最新的
2.git rm --cached submodule專案名 // 將.gitmodules 檔案裡的子模組資料刪除(--cached 會保留子模組目錄,如不需要就不要加)
  P.S 以上兩步 git submodule status 就看不到了,但其實還沒移乾淨
3.將.git/modules 裡的子模組資料夾刪除(如用指令可下 rm -rf submodule_name)



※subtree

一、新增子樹

git subtree add --prefix=子樹名 --squash 路徑或遠端名 master
--prefix=(有等號) 也可寫成 -P(沒等號), 子樹名會變成目錄名,而路徑的內容會在裡面
--squash 如果不加會所有 log 歷史都有,squash 是壓縮的意思,可想成是精簡版,表示只要最新的 log
master 是遠端分支,意思就是從遠端的 master 分支複製過來
路徑或遠端名:使用 git remote add key 路徑,是個鍵值對,設定完後,這個 key 就等同是遠端名了


二、上傳子樹

git subtree push --prefix=子樹名 路徑或遠端名 master
如果只用 git push 不會上傳子樹






三、下載子樹

git subtree pull --squash --prefix=子樹名 路徑或遠端名 master
注意:如果 add 時有 squash,這裡也要加



※ submodule 和 subtree 比較

submodule 是參照的方式,所以操作時,兩個模組是分開的;commit 和子模組會一樣
subtree 是複製的方式,所以操作時還是用主樹操作即可;commit 和子樹不同

沒有留言:

張貼留言