倉(cāng)庫(kù)瘦身方法
問(wèn)題
-
為什么瘦身灼卢?
- 由于每個(gè)人都必須下載文件练对,因此獲取代碼庫(kù)的速度變慢。
- 它們占用服務(wù)器上的大量存儲(chǔ)空間税灌。
- 會(huì)達(dá)到Git倉(cāng)庫(kù)的存儲(chǔ)限制均函。
- 個(gè)人電腦硬盤(pán)空間有限,倉(cāng)庫(kù)較多時(shí)菱涤,占用了大量存儲(chǔ)空間苞也。
-
為什么二進(jìn)制大文件是個(gè)問(wèn)題?
- 在 git 中粘秆,所有和你共用一個(gè)庫(kù)的人如迟,當(dāng)他們把庫(kù)下載下來(lái)時(shí),他們會(huì)得到你這個(gè)項(xiàng)目的完整歷史記錄。一般情況下這沒(méi)什么問(wèn)題——真正的代碼只占很少體積殷勘,但擁有完整的歷史記錄使你能夠?qū)嵤┓植际降暮献鞔嗽佟⒖焖俚玫?diff 結(jié)果以及更多的便利——但項(xiàng)目的歷史記錄會(huì)慢慢膨脹。如果你提交了大文件——比如 100MB 以上——你倉(cāng)庫(kù)的體積會(huì)飛速增長(zhǎng)玲销,并且當(dāng)其他人 clone 這個(gè)倉(cāng)庫(kù)的時(shí)候输拇,他們要下載的數(shù)據(jù)就更多了。最終你會(huì)意識(shí)到你犯了一個(gè)錯(cuò)誤贤斜,但是就算你決定要通過(guò)一個(gè) commit 來(lái)刪除這些文件淳附,它們其實(shí)還在那兒,在你的歷史數(shù)據(jù)中蠢古,下載整個(gè)倉(cāng)庫(kù)所花的時(shí)間不會(huì)有任何變化
方案
- Git 命令
- git-filter-branch 重寫(xiě)存儲(chǔ)庫(kù)會(huì)刪除不需要的歷史記錄奴曙,從而使存儲(chǔ)庫(kù)更小
- git filter-repo 是用于快速重寫(xiě)Git存儲(chǔ)庫(kù)歷史記錄的工具。
- gitlab官方文檔 https://docs.gitlab.com/ee/user/project/repository/reducing_the_repo_size_using_git.html#repository-cleanup
- git-filter-repo用法 https://htmlpreview.github.io/?https://github.com/newren/git-filter-repo/blob/docs/html/git-filter-repo.html#EXAMPLES
- BFG Repo-Cleaner
- git-filter-branch 的替代品 用 Scala 寫(xiě) BFG Repo-Cleaner 草讶,Scala 很適合去處理 git 的不可變數(shù)據(jù)結(jié)構(gòu)洽糟,并且能利用并行開(kāi)發(fā)的優(yōu)勢(shì)。
- 速度更快
- 在 git 中堕战,所有文件和文件夾的數(shù)據(jù)都只存儲(chǔ)一次坤溃,并且每個(gè)都會(huì)有一個(gè)獨(dú)一無(wú)二的 id——git-id。如果大量的 commit 都沒(méi)有修改某個(gè)文件嘱丢,那么這個(gè)文件只會(huì)被保存一次薪介。如果這個(gè)文件有兩個(gè)版本,并且需要在兩個(gè)版本間來(lái)回切換越驻,這個(gè)文件只會(huì)存儲(chǔ)兩次汁政,每個(gè)版本各一次。所以缀旁,如果一個(gè)文件只存儲(chǔ)一次记劈,因?yàn)樗霈F(xiàn)在 100 個(gè) commit 中,就要對(duì)它清理 100 次并巍,這肯定是不現(xiàn)實(shí)的目木。BFG 只對(duì) git 庫(kù)中的每個(gè)對(duì)象清理一次,然后記住它的 git-id懊渡,以后遇到它刽射,不把它計(jì)算在內(nèi)就行了。我們對(duì)功能做了限制——git-filter-branch 能讓你做任何事剃执,而 BFG 不行——以此換來(lái)性能上的巨大改進(jìn)宇葱。
速度的提升還受益于沒(méi)有進(jìn)程間的切換(JVM 會(huì)搞定一切肉盹,不需要在 C 代碼和 bash 代碼間來(lái)回切)巡社,以及能充分利用你的多核電腦椿访。我很高興看到 BFG 會(huì)使你所有的處理器核發(fā)燙,每個(gè)核都在盡其所能地刪除文件和目錄——但是很不幸 git-filter-branch 只能串行處理工作阁最,一個(gè)接一個(gè)地處理 commit——前一個(gè)處理完之前戒祠,無(wú)法開(kāi)始下一個(gè)。BFG 的速度明顯是一大優(yōu)勢(shì)速种。
- 在 git 中堕战,所有文件和文件夾的數(shù)據(jù)都只存儲(chǔ)一次坤溃,并且每個(gè)都會(huì)有一個(gè)獨(dú)一無(wú)二的 id——git-id。如果大量的 commit 都沒(méi)有修改某個(gè)文件嘱丢,那么這個(gè)文件只會(huì)被保存一次薪介。如果這個(gè)文件有兩個(gè)版本,并且需要在兩個(gè)版本間來(lái)回切換越驻,這個(gè)文件只會(huì)存儲(chǔ)兩次汁政,每個(gè)版本各一次。所以缀旁,如果一個(gè)文件只存儲(chǔ)一次记劈,因?yàn)樗霈F(xiàn)在 100 個(gè) commit 中,就要對(duì)它清理 100 次并巍,這肯定是不現(xiàn)實(shí)的目木。BFG 只對(duì) git 庫(kù)中的每個(gè)對(duì)象清理一次,然后記住它的 git-id懊渡,以后遇到它刽射,不把它計(jì)算在內(nèi)就行了。我們對(duì)功能做了限制——git-filter-branch 能讓你做任何事剃执,而 BFG 不行——以此換來(lái)性能上的巨大改進(jìn)宇葱。
實(shí)現(xiàn)(選擇BFG Repo-Cleane 操作簡(jiǎn)單 速度更快)
- BFG Repo-Cleaner (https://rtyley.github.io/bfg-repo-cleaner/)
- 首先刪除不想要文件 并提交
rm file-to-delete
git commit -m "刪除大文件"
git push"
- 下載官網(wǎng)的程序包姜盈。例如我這里下載的為bfg-1.14.0.jar,之后將程序包放到一個(gè)項(xiàng)目文件夾里配阵,重命名為bfg.jar 馏颂。這是一個(gè)Java程序,使用的話需要安裝Java運(yùn)行環(huán)境(https://www.java.com/en/download/manual.jsp)棋傍。
- clone自己的git repo救拉,使用--mirror參數(shù)。
git clone --mirror git@github.com:12134/XXXX.git
- 清除大文件瘫拣、文件夾和檢索大文件 命令
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文件)
- 執(zhí)行完 有一個(gè)問(wèn)題亿絮,這種情況bfg會(huì)保護(hù)當(dāng)前版本(HEAD所指的版本),不去清理麸拄。提示如下派昧。
These are your protected commits, and so their contents will NOT be altered: commit ******* (protected by 'HEAD')
如果說(shuō)當(dāng)前版本已經(jīng)沒(méi)有問(wèn)題,那么這么使用沒(méi)有問(wèn)題拢切。
但是我的當(dāng)前版本也是有需要?jiǎng)h除的文件的蒂萎,在谷歌搜索了一下,找到了解決方法淮椰。
在命令行下加入--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
- 首先刪除不想要文件 并提交
- 在完成上面的指令后豺撑,實(shí)際上這些數(shù)據(jù)/文件并沒(méi)有被直接刪除,這時(shí)候需要使用git gc指令來(lái)清除黔牵。
cd XXXX.git
git reflog expire --expire=now --all && git gc --prune=now --aggressive
- 最后聪轿,更新完本地倉(cāng)庫(kù)后,將數(shù)據(jù)推送到GitHub遠(yuǎn)程倉(cāng)庫(kù)猾浦。按照官網(wǎng)描述陆错,由于之前使用了--mirror參數(shù),推送時(shí)會(huì)推送所有內(nèi)容金赦。(push完成之后放棄舊存儲(chǔ)庫(kù)副本重新clone)
git push
實(shí)現(xiàn)結(jié)果
需要測(cè)試請(qǐng)上碼云建倉(cāng)庫(kù)測(cè)試
GitHub會(huì)報(bào)下面的錯(cuò)
[remote rejected] refs/pull/1/head -> refs/pull/1/head (deny updating a hidden ref)
問(wèn)題詳情(https://stackoverflow.com/questions/34265266/remote-rejected-errors-after-mirroring-a-git-repository)
GitHub所有已清除的拉請(qǐng)求歷史記錄都沒(méi)有被清除音瓷。如果希望你的拉請(qǐng)求,以及它們引用的所有提交/歷史記錄都刪除夹抗,那么在GitHub上的總回購(gòu)大小可以縮小(除了已經(jīng)縮小的默認(rèn)克隆的大小之外)绳慎,需要聯(lián)系GitHub支持