Git 倉庫瘦身方法

倉庫瘦身方法

問題

  • 為什么瘦身?
    • 由于每個人都必須下載文件,因此獲取代碼庫的速度變慢。
    • 它們占用服務(wù)器上的大量存儲空間。
    • 會達(dá)到Git倉庫的存儲限制。
    • 個人電腦硬盤空間有限,倉庫較多時,占用了大量存儲空間。
  • 為什么二進(jìn)制大文件是個問題?
    • 在 git 中,所有和你共用一個庫的人,當(dāng)他們把庫下載下來時,他們會得到你這個項目的完整歷史記錄。一般情況下這沒什么問題——真正的代碼只占很少體積,但擁有完整的歷史記錄使你能夠?qū)嵤┓植际降暮献?、快速得?diff 結(jié)果以及更多的便利——但項目的歷史記錄會慢慢膨脹。如果你提交了大文件——比如 100MB 以上——你倉庫的體積會飛速增長,并且當(dāng)其他人 clone 這個倉庫的時候,他們要下載的數(shù)據(jù)就更多了。最終你會意識到你犯了一個錯誤,但是就算你決定要通過一個 commit 來刪除這些文件,它們其實還在那兒,在你的歷史數(shù)據(jù)中,下載整個倉庫所花的時間不會有任何變化

方案

  • Git 命令
  • BFG Repo-Cleaner
    • git-filter-branch 的替代品 用 Scala 寫 BFG Repo-Cleaner ,Scala 很適合去處理 git 的不可變數(shù)據(jù)結(jié)構(gòu),并且能利用并行開發(fā)的優(yōu)勢。
    • 速度更快
      • 在 git 中,所有文件和文件夾的數(shù)據(jù)都只存儲一次,并且每個都會有一個獨(dú)一無二的 id——git-id。如果大量的 commit 都沒有修改某個文件,那么這個文件只會被保存一次。如果這個文件有兩個版本,并且需要在兩個版本間來回切換,這個文件只會存儲兩次,每個版本各一次。所以,如果一個文件只存儲一次,因為它出現(xiàn)在 100 個 commit 中,就要對它清理 100 次,這肯定是不現(xiàn)實的。BFG 只對 git 庫中的每個對象清理一次,然后記住它的 git-id,以后遇到它,不把它計算在內(nèi)就行了。我們對功能做了限制——git-filter-branch 能讓你做任何事,而 BFG 不行——以此換來性能上的巨大改進(jìn)。
        速度的提升還受益于沒有進(jìn)程間的切換(JVM 會搞定一切,不需要在 C 代碼和 bash 代碼間來回切),以及能充分利用你的多核電腦。我很高興看到 BFG 會使你所有的處理器核發(fā)燙,每個核都在盡其所能地刪除文件和目錄——但是很不幸 git-filter-branch 只能串行處理工作,一個接一個地處理 commit——前一個處理完之前,無法開始下一個。BFG 的速度明顯是一大優(yōu)勢。

實現(xiàn)(選擇BFG Repo-Cleane 操作簡單 速度更快)

  • BFG Repo-Cleaner (https://rtyley.github.io/bfg-repo-cleaner/
    1. 首先刪除不想要文件 并提交
      rm file-to-delete
      git commit -m "刪除大文件"
      git push"
    2. 下載官網(wǎng)的程序包。例如我這里下載的為bfg-1.14.0.jar,之后將程序包放到一個項目文件夾里,重命名為bfg.jar 。這是一個Java程序,使用的話需要安裝Java運(yùn)行環(huán)境(https://www.java.com/en/download/manual.jsp)。
    3. clone自己的git repo,使用--mirror參數(shù)。
      git clone --mirror git@github.com:12134/XXXX.git
    4. 清除大文件、文件夾和檢索大文件 命令
      java -jar bfg.jar --delete-files 123.png XXXX.git (刪除文件)
      java -jar bfg.jar --delete-folders Pods XXXX.git (刪除文件夾)
      java -jar bfg.jar --strip-blobs-bigger-than 100M XXXX.git(大于100M文件)
    5. 執(zhí)行完 有一個問題,這種情況bfg會保護(hù)當(dāng)前版本(HEAD所指的版本),不去清理。提示如下。
      These are your protected commits, and so their contents will NOT be altered: commit ******* (protected by 'HEAD')
      如果說當(dāng)前版本已經(jīng)沒有問題,那么這么使用沒有問題。
      但是我的當(dāng)前版本也是有需要刪除的文件的,在谷歌搜索了一下,找到了解決方法。
      在命令行下加入--no-blob-protection命令,可以解除保護(hù)。使用的命令如下。
      java -jar bfg.jar --delete-files 123.png XXXX.git --no-blob-protection
      java -jar bfg.jar --delete-folders Pods XXXX.git --no-blob-protection
  1. 在完成上面的指令后,實際上這些數(shù)據(jù)/文件并沒有被直接刪除,這時候需要使用git gc指令來清除。
    cd XXXX.git
    git reflog expire --expire=now --all && git gc --prune=now --aggressive
  2. 最后,更新完本地倉庫后,將數(shù)據(jù)推送到GitHub遠(yuǎn)程倉庫。按照官網(wǎng)描述,由于之前使用了--mirror參數(shù),推送時會推送所有內(nèi)容。(push完成之后放棄舊存儲庫副本重新clone)
    git push

實現(xiàn)結(jié)果

需要測試請上碼云建倉庫測試
GitHub會報下面的錯
[remote rejected] refs/pull/1/head -> refs/pull/1/head (deny updating a hidden ref)
問題詳情(https://stackoverflow.com/questions/34265266/remote-rejected-errors-after-mirroring-a-git-repository
GitHub所有已清除的拉請求歷史記錄都沒有被清除。如果希望你的拉請求,以及它們引用的所有提交/歷史記錄都刪除,那么在GitHub上的總回購大小可以縮小(除了已經(jīng)縮小的默認(rèn)克隆的大小之外),需要聯(lián)系GitHub支持

WechatIMG219.png

WechatIMG221.png
WechatIMG222.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容