被吐槽 GitHub倉 庫太大,直接 600M 瘦身到 6M,這下舒服了

2023-04-11 15:00:18

大家好,我是小富~

前言

忙裡偷閒學習了點技術寫了點demo程式碼,打算提交到我那 2000Star 的Github倉庫上,居然發現有5個Issues,最近的一條日期已經是2022/8/1了,以前我還真沒留意過這些,我這人懶得很,原生程式碼提交成功基本就不管了。

倉庫地址:https://github.com/chengxy-nds/Springboot-Notebook

5個Issues中,有個標題"優化本倉庫大小的建議"吸引我了,趕緊點進去看看啥情況,這個哥們說我這個倉庫太大了,倉庫700多M,半天也拉不下來,然後還給我附上了修改建議(不要太貼心哦)。

我不信

開始我還有點不信,這倉庫提交的是我平時寫文章中跑的程式碼demo,每個專案也就十來個檔案几十KB,怎麼會有700M這麼多,不信邪的我趕緊看了下倉庫大小Setting->Repositoriess,居然真有683M這麼多。

於是我趕緊Clone倉庫到本地,看看是不是我提交了什麼大檔案,下載過程確實挺折磨人,不僅慢還經常中斷,在經過不知道多少次重試之後,終於下載下來了。

翻了翻各個專案發現裡邊的確有許多應該忽略的檔案.idea.mvntarget都被我提交了,直接刪除檔案,但並沒有什麼卵用,專案整體size變化不大,應該不是這些檔案的原因。

我用du命令看了下各目錄的檔案大小,發現./springboot-seata-transaction目錄45M,因為裡邊有一個jar直接刪除就行了;而 .git 足足有688M,看來問題就出在這個目錄,重點優化下。

這目錄好大

那麼.git目錄是存放什麼的?為什麼會這麼大呢?

Git系統中,.git目錄中儲存了整個程式碼倉庫的後設資料資訊(包括提交歷史記錄、分支、標籤等)和檔案物件。

我在該目錄上用du命令看了一下,發現 objects 目錄居然有683M,那麼問題就是出在它身上了。

objects目錄之所以這麼大,是因為它儲存了倉庫中的所有歷史版本和資料物件,也就是blobs檔案內容, trees目錄結構, commits提交歷史,它們是 Git 中的三個核心物件型別。

其中:

  • Blobs: 每一個檔案都被視為一個二進位制物件(Blob 物件),它儲存了檔案的所有內容和一些後設資料資訊,如檔名、檔案型別、檔案大小等。當檔案發生變化時,Git 會自動計算並儲存新的 Blob 物件,並將其與先前的 Blob 物件做比較,以確定檔案的變化情況。

  • Trees: 目錄也被視為一個物件(Tree 物件),它儲存了目錄中包含的所有檔案和子目錄的列表,每個列表項包括了檔案或目錄的名稱、型別、許可權等資訊,以及對應檔案或目錄的 Blob 或 Tree 物件的 SHA 校驗和。

  • Commits: 我們每次提交程式碼,就會產生一次Commit, Commit物件儲存了一次程式碼變更的相關資訊,包括作者、提交時間、父提交記錄的 SHA 值、描述資訊等。每個 Commit 物件還包含指向對應程式碼快照的 Tree 物件的 SHA 校驗和。

上邊三種型別的物件組成了Git中的基本資料單元,通過這些物件的組合和連結,才構建出完整的提交歷史,並跟蹤程式碼庫中每個檔案的變化歷史。這個目錄是Git中最重要的目錄之一,所以對它操作要謹慎,不然很容易丟失歷史記錄。

瘦身利器

儘管我們知道了大檔案的位置,可具體該刪除哪些檔案無從下手啊,objects目錄下都是些壓縮檔案,弄不好整個倉庫都得報廢。

好在提Issues的兄弟還給推薦了個Git倉庫瘦身的工具,該說不說真的貼心啊。

這個Git倉庫清理工具叫BFG Repo-Cleaner,可以幫助我們篩選、清理大檔案物件,官方檔案地址:https://rtyley.github.io/bfg-repo-cleaner ,接下來看看這工具咋用。

注意:在做以下操作之前,一定要備份!!! 一定要備份!!! 一定要備份!!!

1、下載安裝

BFG 是以java -jar的方式啟動,首先安裝不低於JDK8+ 的環境,並下載 BFG 的Jar包。

$ wget https://repo1.maven.org/maven2/com/madgag/bfg/1.14.0/bfg-1.14.0.jar

2、clone 倉庫

在 clone 倉庫的時候推薦使用--mirror引數,將源倉庫的所有分支、標籤以及提交歷史都完整地克隆到本地,只會拉取.git目錄的相關檔案。

$ git clone --mirror git://example.com/Springboot-Notebook.git

3、查詢大檔案

bfg-1.14.0.jarSpringboot-Notebook.git 放在同一級目錄下,執行下邊的命令過濾出大於20M的檔案物件。

# 查詢出大於20M的需要清理的檔案
$ java -jar bfg-1.14.0.jar --strip-blobs-bigger-than 20M Springboot-Notebook.git

看到過濾出了很多大檔案,包含了Issues中兄弟提到的那個Jar包。

4、刪除大檔案

使用--delete-files命令逐一的將大檔案刪除,如果提示分支是被保護的可以加上--no-blob-protection命令執行。

# 查詢出大於20M的需要清理的檔案
$ java -jar bfg.jar --delete-files Cyrillic.traineddata  Springboot-Notebook.git 

5、GC 回收垃圾

上邊我們雖然過濾、刪除了大檔案,此時倉庫的大小仍然沒有變化,進入Springboot-Notebook.git倉庫內,執行 git reflog expiregit gc命令,壓縮 Git 庫中的歷史版本、清除廢棄的、過期的物件,這個過程會耗費較長的時間。

# 進入目錄
$ cd Springboot-Notebook.git

# 執行git gc 回收垃圾
$ git reflog expire --expire=now --all && git gc --prune=now --aggressive

# 推播
$ git push

最後推播程式碼到遠端倉庫,在看倉庫的大小已經降到了108M,效果挺顯著,剩下的108M應該就是我頻繁提交導致的了,查了下我居然有127次提交之多。

每次提交都會生成一次快照,這些快照可能包含大量的檔案和程式碼,頻繁提交會導致版本庫中快照的數量增加。Git使用的是一種增量儲存方式,每次提交只儲存發生了變化的檔案和程式碼。

但是,如果頻繁提交的變化較小,比如只是修改了幾個字元或者行末空格,Git可能無法正確地檢測出這些變化,而將整個檔案都儲存起來,也會增加了.git檔案的大小。

徹底一點

後來我想了想這個倉庫存在的意義,不就是讓大家看著文章跑demo程式碼嘛,能快速的下載併成功執行才是他們在乎的,誰又會在意提交記錄。那我乾脆徹底一點,清理掉倉庫的所有提交記錄,一勞永逸。

那麼操作起來就得小心一點了,畢竟2000star,別把倉庫弄嘎了,既要清除一個分支上的所有提交記錄,同時又不能刪除這個分支本身,其實我們可以迂迴一下。

我們首先使用 --orphan 命令建立一個全新的分支new-branch,這個新建的分支和其他分支沒有任何關係,它不會包含任何先前的提交記錄或者歷史記錄。相當於新建了一個乾淨的空分支,並讓該分支指向一個全新的根節點。

git checkout --orphan <new-branch-name>

然後 commit 全部的專案檔案到這個分支,暫不需要推到遠端倉庫。

git add -A
git commit -am "Initial commit"

接著刪除舊的分支,並把新建的分支名改成舊分支名稱,推到遠端倉庫就行了。

# 

git branch -D <old-branch-name>
git branch -m <old-branch-name>
git push -f origin <old-branch-name>

在推完程式碼後我再次去看了下倉庫的大小,現在就只有6.33M了,如果不是臉部辨識專案中有幾個必要的SDK包,應該還能在小點。

總結

以我自己的親身經歷做為反面教材,提醒大家操作Git要謹慎,工作中嚴禁提交該忽略的檔案;提交程式碼要控制節奏,不能隨心所欲,尤其是團隊共同作業開發;如果發現.git檔案太大,推薦使用Git LFS來管理大檔案,千萬不要像我這麼操作,畢竟隨意刪除提交歷史記錄,在哪個公司都是不合規的。

重點感謝下提出建議的大兄弟