Git從庫中移除已刪除大文件


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

刪除大文件
方法很簡單,就是先找到大文件對象再刪除。

先提交所有更改

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

$ git gc
1
運行count-objects 查看空間使用,size-pack 是以千字節為單位表示的 packfiles 的大小,因此已經使用了大約150MB 。

$ git count-objects -v
1


運行底層命令 git verify-pack 以識別出大對象,對輸出的第三列信息即文件大小進行排序.

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


注:可以看到對底下那個就是大文件。

使用 rev-list 命令,傳入 - -objects 選項,它會列出所有 commit SHA 值,blob SHA 值及相應的文件路徑,這樣查看 blob 的文件名。

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


將該文件從歷史記錄的所有 tree 中移除。

$ git log --pretty=oneline --branches -- spark-assembly-1.3.1-hadoop2.4.0.jar
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


注:- -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
查看空間使用

$ git count-objects -v
1
如果真的要完全把這個對象刪除,可以運行 git prune 命令。
---------------------
作者:白 楊
來源:CSDN
原文:https://blog.csdn.net/zcf1002797280/article/details/50723783
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!

 

 

http://blog.csdn.net/lihuanshuai/article/details/37345565

Git的底層並沒有采用 CVS、SVN 底層所采用的那套增量式文件系統,而是采用一套自行維護的存儲文件系統。當文件變動發生提交時,該文件系統存儲的不是文件的差異信息,而是文件快照,即整個文件內容,並保存指向快照的索引。這種做法,提高 Git 分支的使用效率;但也容易導致代碼倉庫中內容重復程度過高,從而倉庫體積過大。當遇到這種情況時,或者需要將倉庫推送到遠程主機時,就需要Git中的gc(garbage collect)功能,也就是垃圾回收功能。

大體來說,當運行 "git gc" 命令時,Git會收集所有松散對象並將它們存入 packfile,合並這些 packfile 進一個大的 packfile,然后將不被任何 commit 引用並且已存在一段時間 (數月) 的對象刪除。 此外,Git還會將所有引用 (references) 並入一個單獨文件。

就細節而言,Git做了這幾件事:

 

  • pack_refs 過程
  • reflog expire 過程
  • repack 過程
  • prune 過程
  • rerere 過程

 

pack_refs 過程相當於執行"git pack-refs --all --prune",它會將$GIT_DIR/refs目錄下的所有heads和tags打包成一個文件並保存為$GIT_DIR/packed-refs下。

reflog expire 過程相當於執行"git reflog expire --all",它會將刪除所有超過期限而且沒有被refs涉及的reflog條目。

repack 過程相當於執行"git repack -d -l",一般情況下還會包括"-A"選項,它會將所有未被包含在一個pack的松散對象連結成一個pack,也會將現有的pack重新組織為一個新的更有效率的pack,並刪除冗余的pack(如果她們中存在不可達的松散對象,會先把這些對象釋放出來)。

prune 過程相當於執行"git prune --expire",他會刪除所有過期的、不可達的且未被打包的松散對象。

rerere 過程相當於執行"git rerere gc",這種情形下似乎沒什么用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM