處理.git資料夾過大出現臃腫問題-filter-branch和BFG工具

2023-07-13 18:00:16

Git開發手冊

git一些不常用的命令記不住,可以檢視git開發手冊(https://m.php.cn/manual/view/34957.html)

1、.git/objects/pack 檔案過大

今天從git拉取專案進行開發的時候克隆的很慢,還以為是網速的問題。檢視了一些git命令框的拉取網路速度發現網速也很快,克隆下來後才發現是.git資料夾太大,專案程式碼佔用很小。發現了是git的問題後,就第一時間查詢下是那個地方出的問題導致檔案過大。

進入.git目錄後發現是/objects/pack目錄下面的xxx.pack檔案佔用過大。

2、pack檔案過大出現的原因

在開發過程中有時候不小心上傳了大檔案,雖然後面在目錄裡面刪除了,但會被git記錄下來。這樣慢慢的記錄的越來越多,就變為了目前這樣檔案太大。出現臃腫。我們可以使用git自帶的filter-branch工具或者BFG進行倉庫清理。

3、使用git filter-branch清理

進入git命令框,輸入命令。首先查詢出3個大檔案資訊

git verify-pack -v .git/objects/pack/pack-xxx.idx | sort -k 3 -n | tail -3 (xxx你的.git的pack目錄檔案)

查詢結果

73671b13992abba02a7fa56d37735d4ac01803b1 blob   62992368 62936889 132214388

在根據上面的檔名的編碼ID:73671b13992abba02a7fa56d37735d4ac01803b1 查詢出大檔案的名稱:

git rev-list --objects --all | grep 73671b13992abba02a7fa56d37735d4ac01803b1

上面的為單個查詢,我們也可以直接查詢多個,把上面的兩個命令合併一起執行。

git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -10 | awk '{print$1}')" #查詢前10個大檔案

通過命令查詢出檔案資訊,然後將該檔案從歷史記錄的所有 tree 中移除,執行命令從歷史中刪除指定的大文:

git filter-branch --force --index-filter "git rm -rf --cached --ignore-unmatch 檔案/資料夾" --prune-empty --tag-name-filter cat -- --all #檔案/資料夾 是通過上面查詢出來的大檔案路徑和名稱

執行成功後需要刪除和重建索引

git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin 

然後設定歷史記錄的過期時間為現在,預設為90天。

git reflog expire --expire=now --all #所有未關聯物件過期時間為現在

通過gc清理檔案並優化本地儲存庫

git gc --aggressive --prune=now

強制提交

git push --all --force origin

執行完畢上面命令,一個大檔案我們就清理完畢了,如果有多個大檔案需要一個檔案一個檔案的執行。當大檔案都清理完畢我們可以檢視當前目錄下個檔案及目錄佔用空間大小

du -sh .git

如果輸出檔案過大,可以繼續查詢相關大檔案進行刪除。

git count-objects -v #計算解包的物件數量及其磁碟消耗量

4、高效大檔案清理工具 BFG

官網地址:BFG (https://rtyley.github.io/bfg-repo-cleaner/ )BFG是git-filter-branch的替代品,官方介紹說要比 git-filter-branch 快上10~720x,本人使用了下,確實很快。值得我們去使用。需要去官網下載bfg.jar。也可以去映象倉庫下載(https://repo1.maven.org/maven2/com/madgag/bfg/)這裡使用1.14.0版本。由於是jar包執行bfg需要具備java環境。簡單介紹下命令,也可以自己去官網查詢相關命令。

通過 --mirror  拉取自己專案的.git 檔案, --mirror引數只拉取.git檔案不克隆程式碼,防止操作失誤修改專案程式碼。

git clone --mirrot xxx.git

查詢前10個大檔案

git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -10 | awk '{print$1}')"

通過刪除目錄檔案刪除

java -jar bfg.jar --delete-folders {dev} --no-blob-protection project.git #{dev} 刪除dev目錄下面的所有檔案

通過檔案大小刪除

java -jar bfg.jar --strip-blobs-bigger-than 10M project.git #刪除檔案大於10M

通過檔案名字刪除,先通過查詢大檔案查詢出資料,然後通過檔名稱執行該命令刪除:

java -jar bfg.jar --delete-files "xxxx"  project.git

java -jar bfg.jar --delete-files "xxxx" --no-blob-protection project.git

刪除敏感資訊

java -jar bfg.jar --replace-text pwd.txt project.git

pwd.txt自己定義需要移除資料的文字,具體語法自己可以查詢相關檔案。

設定過期時間為現在 & 清理檔案

git reflog expire --expire=now --all && git gc --prune=now --aggressive

推播到遠端

git push --mirror

最後我們在執行下 du -sh .git 命令查詢一些.git資料夾大小,發現一些沒有的檔案我們已經清理乾淨了。後面需要重新從git克隆程式碼,不要使用之前的.git檔案進行提交。否則檔案會變得更大。