Git從庫中移除已刪除大檔案
寫在前面
大家一定遇到過在使用Git時,不小心將一個很大的檔案新增到庫中,即使刪除,記錄中還是儲存了這個檔案。以後不管是拷貝,還是push/pull都比較麻煩。今天在上傳工程到github上,發現最大隻能上傳100MB大小檔案,在本地git庫中有一個150MB檔案,雖然已經刪除,但還儲存了記錄。下面教大家如何從庫中徹底刪除無效大檔案。
刪除大檔案
方法很簡單,就是先找到大檔案物件再刪除。
-
先提交所有更改
$ git commit -am "commit all"
- 1
- 1
-
對倉庫進行gc操作
$ git gc
- 1
- 1
-
執行count-objects 檢視空間使用,size-pack 是以千位元組為單位表示的 packfiles 的大小,因此已經使用了大約150MB 。
$ git count-objects -v
- 1
- 1
-
執行底層命令 git verify-pack 以識別出大物件,對輸出的第三列資訊即檔案大小進行排序.
$ git verify-pack -v .git/objects/pack/pack-8eaeb...9e.idx | sort -k 3 -n | tail -3
- 1
- 1
注:可以看到對底下那個就是大檔案。
-
使用 rev-list 命令,傳入 - -objects 選項,它會列出所有 commit SHA 值,blob SHA 值及相應的檔案路徑,這樣檢視 blob 的檔名。
$ git rev-list --objects -
- 1
- 1
-
將該檔案從歷史記錄的所有 tree 中移除。
$ git log --pretty=oneline --branches -- spark-assembly-1.3.1-hadoop2.4.0.jar
- 1
- 1
-
用 filter-branch 命令重寫從 646784 開始的所有 commit 才能將檔案從 Git 歷史中完全移除。
git filter-branch --index-filter 'git rm --cached --ignore-unmatch spark-assembly-1.3.1-hadoop2.4.0.jar' -- 646784d95f347749517a67c50c117f4bf85d0b42
- 1
- 1
注:- -index-filter 選項類似於 - -tree-filter 選項,但這裡不是傳入一個命令去修改磁碟上籤出的檔案,而是修改暫存區域或索引。不能用 rm file 命令來刪除一個特定檔案,而是必須用git rm - -cached 來刪除它 ── 即從索引而不是磁碟刪除它。這樣做是出於速度考慮 ── 由於 Git 在執行你的 filter 之前無需將所有版本簽出到磁碟上,這個操作會快得多。也可以用 - -tree-filter來完成相同的操作。git rm 的 - -ignore-unmatch 選項指定當你試圖刪除的內容並不存在時不顯示錯誤。最後,因為你清楚問題是從哪個 commit 開始的,使用 filter-branch 重寫自 64678 這個 commit 開始的所有歷史記錄。不這麼做的話會重寫所有歷史記錄,花費不必要的更多時間。
-
現在歷史記錄中已經不包含對那個檔案的引用了。不過 reflog 以及執行 filter-branch 時 Git 往.git/refs/original 新增的一些 refs 中仍有對它的引用,因此需要將這些引用刪除並對倉庫進行 repack 操作。在進行 repack 前需要將所有對這些 commits 的引用去除。
\$ rm -Rf .git/refs/original \$ rm -Rf .git/logs/ \$ git gc
- 1
- 2
- 3
- 1
- 2
- 3
-
檢視空間使用
$ git count-objects -v
- 1
- 1
-
如果真的要完全把這個物件刪除,可以執行 git prune 命令。