拋磚系列之git倉庫拆分工具git-filter-repo

2022-09-01 18:01:37

最近負責把團隊內的git倉庫做了一次分拆,解鎖一個好用的工具git-filter-repo,給大夥拋磚一波,希望以後遇到類似場景時可以信手拈來。

背景

筆者團隊目前是把業務相關的java專案都放到了一個git倉庫中,發展初期專案較少放到一塊圖的就是一個方便,但是幾年下來隨著專案、人員、玩法等多了以後逐漸顯現出一些問題,主要痛點有以下:
1.效率:更新程式碼緩慢,會下載很多我不關心的內容,既影響開發效率也影響jenkins打包的效率;
2.衝突:合併程式碼衝突率顯著增高,而且一旦衝突往往很難解決,兄弟們苦不堪言,程式碼合併相互推諉;
3.許可權:需要遵循最小範圍、按需授權等原則最大限度保證程式碼不外洩,現有的「大鍋飯」模式顯然不滿足。

期望

拆分以後每個專案一個git倉庫,需要保留歷史提交記錄,方便以後回溯。

 

 為了說明問題,上圖是我以交易業務域為場景假想了一個簡化版倉庫,trade倉庫下涵蓋了三個java專案,分別是discount、order、paygate,拆分以後會變成discount、order、paygate三個倉庫。

第一次嘗試

我初次拿到這個任務的時候想,這個很簡單啊,把trade複製三份然後分別改名為trade-order、trade-paygate、trade-discount,並把多餘的刪除,看起來像這樣: 

 

 

 

 

倉庫拆分第一步似乎已經完成,接下來看看歷史記錄有沒有丟失:

1.單個檔案提交歷史是否完整—右鍵order_readme.txt->git->show history(idea整合的檢視檔案git歷史功能),很完整,沒有問題。

 

 

2.新倉庫提交歷史是否完整—右鍵trade-order->git->show history,初看沒什麼問題,再看似乎不夠完美,trade-order包含了拆分之前所有的提交歷史,雖然不影響使用,但提交歷史多了同樣影響效率,必須再優化一波。

 

 

 

第二次嘗試

第一次拆分之後的trade-order之所以包含所有提交歷史是因為我選擇的拆分策略是將原來的倉庫複製出來然後刪除多餘的專案,對於提交歷史並沒有特殊處理,git的提交歷史在.git目錄下,真實的倉庫.git目錄接近900兆,這次的目標是將多餘的提交歷史剔除,靠人工剔除不現實,需要尋覓一款趁手的工具來行使清道夫的職責。

 

網路上對於git倉庫拆分大致有三類工具,分別是subtree、filter-branch、filter-repo,filter-repo雖屬後起之秀,似乎有取而代之前二者的趨勢,同時前二者也有不少的追捧著,一時間不好抉擇。

 

機緣巧合下看到了github官方的一篇文章https://docs.github.com/cn/get-started/using-git/splitting-a-subfolder-out-into-a-new-repository,裡面提到的拆分工具也是filter-repo,我也就選擇跟風一次,畢竟只是臨時用到的一個工具,沒必要花太多時間去選型,走不通了立馬切換都來得及,畢竟試錯的成本很低,這裡順便囉嗦一句,如果是一個技術框架、中介軟體的選型可不能這麼草率,不能簡單的說大廠都用了我們就用,還是要結合實際情況去斟酌,比如公司技術棧、團隊人員配比、運維熟悉度等多緯度綜合考慮,畢竟是要長期執行且替換的代價巨大。

 

關於git-filter-repo的下載安裝請前往推薦閱讀2中的地址自行獲取,這裡就不囉嗦,下面我們直接開始。

1.開啟 Git Bash

2.克隆要拆分的倉庫

git clone https://xxx/trade

3.將當前工作目錄更改為您克隆的倉庫

cd trade

4.要從倉庫中的其餘檔案過濾出該子資料夾,請執行 git filter-repo,提供以下資訊:

--path FOLDER-NAME:專案中您要從其建立單獨倉庫的資料夾。

git filter-repo --path order/

5.將倉庫改名為trade-order

現在,該倉庫應僅包含order目錄下的內容。

 

驗證下提交歷史:

1.單檔案提交歷史沒有問題,如下圖

 

 2.倉庫整體提交歷史沒有問題,只包含order目錄下檔案的提交歷史,沒有把其他的帶過來,如下圖

 

 這次應該是穩了,我跟同事炫耀我的勞動成果,迫切的希望得到他們的讚許,結果換來的卻是另一個新問題:「這個結構是不是能優化下,現在倉庫是兩級trade-order/order,能不能只保留order這一級。」

第三次嘗試

雖然上面的「trade-order/order「看起來也能用,但是多一級無用目錄的確有點醜陋,而且會徒增新同學的困惑,說幹就幹,繼續優化。

 

使用--subdirectory-filter指令保留order/下內容並將order提升為根目錄

 git filter-repo --subdirectory-filter order/ 

現在目錄變成了下面這樣

trade-order/

    .git/

    doc/

       order_readme.txt

最後只需要將trade-order改名為order即可大工告成,提交歷史也完整的保留了下來。

 

 

 

推薦閱讀

1.https://docs.github.com/cn/get-started/using-git/splitting-a-subfolder-out-into-a-new-repository

2.https://github.com/newren/git-filter-repo

3.https://htmlpreview.github.io/?https://github.com/newren/git-filter-repo/blob/docs/html/git-filter-repo.html#EXAMPLES

 

文中只是提及了git-filter-repo的部分指令,更多有意思的玩法請前往推薦閱讀3中的EXAMPLES自行解鎖。

 

最後獻圖一張,下雨天拍到一隻出來放風的小蝸牛