1. 程式人生 > >Git從庫中移除已刪除大檔案

Git從庫中移除已刪除大檔案

寫在前面

大家一定遇到過在使用Git時,不小心將一個很大的檔案新增到庫中,即使刪除,記錄中還是儲存了這個檔案。以後不管是拷貝,還是push/pull都比較麻煩。今天在上傳工程到github上,發現最大隻能上傳100MB大小檔案,在本地git庫中有一個150MB檔案,雖然已經刪除,但還儲存了記錄。下面教大家如何從庫中徹底刪除無效大檔案。

刪除大檔案

方法很簡單,就是先找到大檔案物件再刪除

  1. 先提交所有更改

     $ git commit -am "commit all"
    • 1
    • 1
  2. 對倉庫進行gc操作

     $ git gc
    • 1
    • 1
  3. 執行count-objects 檢視空間使用,size-pack 是以千位元組為單位表示的 packfiles 的大小,因此已經使用了大約150MB 。

     $ git count-objects -v
    • 1
    • 1

    這裡寫圖片描述

  4. 執行底層命令 git verify-pack 以識別出大物件,對輸出的第三列資訊即檔案大小進行排序.

    $ git verify-pack -v .git/objects/pack/pack-8eaeb...9e.idx | sort -k 3 -n | tail -3
    • 1
    • 1

    這裡寫圖片描述

    注:可以看到對底下那個就是大檔案。

  5. 使用 rev-list 命令,傳入 - -objects 選項,它會列出所有 commit SHA 值,blob SHA 值及相應的檔案路徑,這樣檢視 blob 的檔名。

    $ git rev-list --objects -
    -all | grep 185ab8d
    • 1
    • 1

    這裡寫圖片描述

  6. 將該檔案從歷史記錄的所有 tree 中移除。

    $ git log --pretty=oneline --branches -- spark-assembly-1.3.1-hadoop2.4.0.jar
    • 1
    • 1

    這裡寫圖片描述

  7. 用 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 開始的所有歷史記錄。不這麼做的話會重寫所有歷史記錄,花費不必要的更多時間。

  8. 現在歷史記錄中已經不包含對那個檔案的引用了。不過 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
  9. 檢視空間使用

     $ git count-objects -v
    • 1
    • 1
  10. 如果真的要完全把這個物件刪除,可以執行 git prune 命令。