清理git倉庫

參考html

https://harttle.land/2016/03/22/purge-large-files-in-gitrepo.htmlgit

https://git-scm.com/docs/git-rev-listpost

https://git-scm.com/docs/git-filter-branchspa

https://git-scm.com/docs/git-verify-pack3d

該文章是本身操做時查找資料的實踐內容,內容徹底來自上面的做者。code

前言

開發久了,有一些很老的東西,好比一開始沒有拆分後來拆分到別的倉庫的代碼,編譯的一些類庫,或是後面刪除掉的無用的模塊,放在倉庫中,每次clone,都很是大,能夠經過git的一些方法查找,而且從倉庫中刪除。htm

特別注意

這是個很危險的動做,有可能會丟失數據,因此操做以前最好備份或是確保刪除的不是關鍵信息。由於作了這個操做這些東西會永遠從你的git倉庫中刪除,而且再也找不到任何信息,沒法還原,全部的歷史信息都會被重寫。blog

刪除一個文件

git filter-branch -f --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch <file>' --tag-name-filter cat -- --all

這裏的命令就是把每一次提交都執行一次git rm -rf --cached --ignore-unmatch <file>的命令,這個命令就是把一個文件從git的跟蹤倉庫中刪除。具體參考 https://www.cnblogs.com/studywithallofyou/p/11772684.html排序

--index-filter參數用來指定一條Bash命令,而後Git會檢出(checkout)全部的提交, 執行該命令,而後從新提交。這樣的話,咱們就是在每一個提交的記錄下,調用命令,移除<file>,而後再提交,這個文件便從Git的全部記錄中徹底消失了。開發

刪除一個文件夾

這個功能主要就是靠git rm的不一樣參數實現,也就是git filter-branch負責重寫每次提交的歷史,具體操做就是--index-filter指定的一條命令。上面的是刪除一個文件,換成刪除文件夾的,就能夠指定刪除某個文件夾下的內容。好比一開始咱們提交了一個目錄,裏面都是一些編譯生成的類庫,後來不須要了,能夠把它從歷史中刪掉。

git filter-branch -f --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch <folder>' --tag-name-filter cat -- --all

尋找大文件的ID

若是咱們忘記了歷史中哪些文件比較大,又想清理倉庫,那麼就能夠用git verify-pack來查找。這個命令的做用就是列出來每次提交的內容中的詳細信息,其中包含了提交內容的大小。

$ git verify-pack -v .git/objects/pack/*.idx
8fa15d279de33ce28a3289fd33951374084231e4 tree   135 137 144088922
a44a50b2ffb1f8283c8e64aafb8e7628249d7453 tree   33 43 144089059
b57d99f38fe22491e4a2d30c2b081ecb7bbb329c tree   99 97 144089102
2d4ffaffc11758d561ea1a6d57dd8ee17ee1d836 blob   644952 644959 144089199
8cf81ebfeec409f19e7a47a76517317f3bfa268d blob   695898 695871 144734158

-v(verbose)參數是打印詳細信息。

輸出的第一列是提交的index id,第二列表示文件(blob)或目錄(tree),第三列是文件大小。 如今獲得了全部的文件ID及其大小,而後咱們就能夠經過寫一些腳本排序找出最大提交內容的index。

先按照第三列排序,並取最大的5條,而後打印出每項的第一列(index id):

$ git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -5 | awk '{print$1}')"
f846f156d16f74243b67e3dabec58a3128744352 
4a1546e732b2e2a352b7bf220c1a22ad859abf89 
f72d04efe6d0b41b067f9fbbc62455f28d3670d2 
49bdf300ddf57d1946bc9c6570d94a38ac9d6a50 
9c073d4177af5d2e43ada41f92efb18d9462a536

這條命令的做用就是,顯示到git倉庫目錄中過濾每一條提交index的信息,而後把這些信息中,按照第三行也就是大小排序,而後把最大的幾個篩選出來,最後只打印對應的index id就能夠了。

文件名與ID映射

上面咱們僅僅獲得的是提交的index,仍是不知道這些裏面哪些文件比較大,由於git rm須要指定文件名稱。這時就須要git rev-list命令,這個命令的做用是列出來一個提交裏面的內容信息。

$ git rev-list --objects --all
c252878ac09a3979a80520b82a71dc2dae4529f9
7bc7d05c6097063f531580ba4c32921464a6c456 _drafts
dcce26ed53fbb869dc7d5b71742d2f9e523bfe42 _layouts
414186c794a0d58695abb75c548bdbfec1de2763 _layouts/default.html
1934eeffe3d242375510dff28cffa6de6b3de367 _layouts/post.html
5f14647875f2177a6d37b8bfbcdb4629af595b64 _posts
6cdbb293d453ced07e6a07e0aa6e580e6a5538f4 _posts/2013-10-12-2.md

--objects:列出該提交涉及的全部文件ID。
--all:全部分支的提交,至關於指定了位於/refs下的全部引用。

獲得文件名列表

若是內容很少,你能夠按照上面最大index的列表,而後一個個經過git rev-list來查看哪些文件比較大,通常也不是特別多,若是比較多或是想之後使用,能夠再寫一個腳本,排序出最大的文件列表。

$ git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -5 | awk '{print$1}')"
f846f156d16f74243b67e3dabec58a3128744352 assets/img/recent-badge.psd
4a1546e732b2e2a352b7bf220c1a22ad859abf89 assets/img/album/me/IMG_0276.JPG
f72d04efe6d0b41b067f9fbbc62455f28d3670d2 assets/img/album/me/IMG_0389.JPG
49bdf300ddf57d1946bc9c6570d94a38ac9d6a50 assets/img/album/me/IMG_0813.JPG
9c073d4177af5d2e43ada41f92efb18d9462a536 assets/img/album/me/IMG_0891.JPG

上面的命令就是先經過rev-list列出全部index對應的文件信息,而後經過咱們上面查找出的最大的提交index,經過grep過濾出來。這樣就能夠列出來上面查找的最大的提交index中全部的文件信息。

而後就能夠從裏面找出能夠的文件刪除了。刪除完成後記着push到遠程分支,若是push報錯,能夠經過下面命令,強制把全部分支的內容推送到遠程。到此結束。

git push origin --force --all
相關文章
相關標籤/搜索