摘要:維護著一個微型的文件系統,其中的文件也被稱作數據對象。經過我的驗證,確實是這個文件夾中的文件占了磁盤上的空間。與大部分版本控制系統的差別是很大的,比如等等,使用的是增量文件系統就是說它們存儲每次提交之間的差異。
最近在開發一個新應用,有一天在gitlab上clone代碼的時候發現我的應用竟然有170+M,明明是一個全新的應用,代碼都沒有幾行呢,為什么會有這么大呢?
后來經過了解Git的原理,解決了這個問題,把相關內容記錄下來。分享一下。
Why我的一個新應用竟然要170+M,這是打死我我也不會信的,于是就開始分析為什么會這么大。
step 1. 把代碼拉到本地git clone git@github.com:hollischuang/Architecture-Evolution.git
只是用這個地址舉例,實際并不是這個項目。
step 2. 查看哪個文件占用的空間比較大$cd Architecture-Evolution $du -d 1 -h 174M ./.git 264K ./test 96K .
于是,發現是.git目錄自己就占用了174M,了解Git的人都知道,.git目錄是git自己生成的,記錄了git倉庫的相關信息的。看到這里其實并不難知道原因。
Git 維護著一個微型的文件系統,其中的文件也被稱作數據對象。所有的數據對象均存儲于項目下面的 .git/objects中。
經過我的驗證,確實是.git/objects這個文件夾中的文件占了磁盤上174M的空間。
也就是說,只要我有一次將一個大文件誤提交了,那么即使我后面把它刪除了,但是,實際上在.git中,這個文件還是存在的,雖然我們可能再也不需要他了,但是他還在那里默默的存在著。。。
Git與大部分版本控制系統的差別是很大的,比如Subversion、CVS、Perforce、Mercurial 等等,使用的是“增量文件系統” (Delta Storage systems), 就是說它們存儲每次提交(commit)之間的差異。Git正好與之相反,它會把你的每次提交的文件的全部內容(snapshot)都會記錄下來。這會是在使用Git時的一個很重要的理念。
也就是說,如果我又一次把一個大文件務提交到git倉庫中了,那么,下次提交時,即使你只改動了某個文件的一行內容,Git 也會生成一個全新的對象來存儲新的文件內容。
因為以上兩個特性,我回想起我的一次手殘行為:
剛剛創建一個應用之后,我快速的寫完代碼,編譯,運行,發現沒啥問題之后,我準備先把他發布掉,于是我開始創建git倉庫,并嘗試把代碼提交上去,這時我并沒有創建.gitignore文件,我直接git add . git commit -m "init" git push一氣呵成的執行了熟悉的操作。
相信聰明的人已經發現了,逗比啊,我在編譯代碼之后,會有很多jar被我down到target目錄下。我直接git add.把target下面的jar包,war包等這些也直接提交了。。。雖然后面我意識到,并且刪除了這些文件,然后再次提交,但是由于剛我們說過的原因,這些文件依然占用著我的空間。。。
更多關于git的原理內容參見:Git 內部原理
How問題已經定位到了,接下來就是要解決問題了。如果對git的原理及命令了解的比較多的話,這個問題還是比較好解決的,由于當時博主并不十分了解git的原理,所以做了一些知識儲備之后才開始動手的。(Git 之術與道 — 對象、為什么你的 Git 倉庫變得如此臃腫)
Step 1 查看哪些歷史提交過文件占用空間較大使用以下命令可以查看占用空間最多的五個文件:
git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -5 | awk "{print$1}")"
rev-list命令用來列出Git倉庫中的提交,我們用它來列出所有提交中涉及的文件名及其ID。 該命令可以指定只顯示某個引用(或分支)的上下游的提交。step 2. 重寫commit,刪除大文件--objects:列出該提交涉及的所有文件ID。
--all:所有分支的提交,相當于指定了位于/refs下的所有引用。
verify-pack命令用于顯示已打包的內容。
使用以下命令,刪除歷史提交過的大文件:
git filter-branch --force --index-filter "git rm -rf --cached --ignore-unmatch big-file.jar" --prune-empty --tag-name-filter cat -- --all
上面腳本中的big-file.jar請換成你第一步查出的大文件名,或者這里直接寫一個目錄。
filter-branch命令可以用來重寫Git倉庫中的提交--index-filter參數用來指定一條Bash命令,然后Git會檢出(checkout)所有的提交, 執行該命令,然后重新提交。
–all參數表示我們需要重寫所有分支(或引用)。
在重寫提交的過程中,會有以下日志輸出:
Rewrite 6cdbb293d453ced07e6a07e0aa6e580e6a5538f4 (266/266) # Ref "refs/heads/master" was rewritten
如果顯示 xxxxx unchanged, 說明repo里沒有找到該文件, 請檢查路徑和文件名是否正確,重復上面的腳本,把所有你想刪除的文件都刪掉。
step 3. 推送修改后的repo以強制覆蓋的方式推送你的repo, 命令如下:
git push origin master --forcestep 4. 清理和回收空間
雖然上面我們已經刪除了文件, 但是我們的repo里面仍然保留了這些objects, 等待垃圾回收(GC), 所以我們要用命令徹底清除它, 并收回空間,命令如下:
rm -rf .git/refs/original/ git reflog expire --expire=now --all git gc --prune=now
至此,我們已經徹底的刪除了我們不想要的文件。
原文鏈接
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/96453.html
摘要:優化空間不大主要關注另外兩個上面。目前為止,項目打包后的大部頭就是,這個目前的優化空間較小。當然,從整體優化的大維度上來說優化的點還有很多,這個文章繼續更新下去。 項目現狀 項目是一個數據監測平臺,引入了ehcart和three.js 負責項目的數據可視化;打包后,體積高達2.1M,這個體積相比于我的項目規模來說就顯得稍有笨重了 使用webpack-bundle-analyzer分析了...
摘要:首發公眾號程序員日記作者賢榆的榆如果你覺得有幫助歡迎關注贊賞轉發閱讀時間字分鐘注先簡述一下時間線月日周日上午拿到新的下午裝好系統晚上從舊的上遷移數據到新。到月號還沒有修復,官方也還沒有任何關于這方面的恢復。 showImg(https://segmentfault.com/img/remote/1460000016418427?w=690&h=365); 首發公眾號:Android程序...
摘要:問題分析隨著回滾版本的放量,主端崩潰逐漸回歸正常,進一步坐實了新版本存在問題。內容非常多但都是重復的,看起來進程沒有啟動,導致連接端一直在進行重連。背景公司的主打產品是一款跨平臺的 App,我的部門負責為它提供底層的 sdk 用于數據傳輸,我負責的是 Adnroid 端的 sdk 開發。sdk 并不直接加載在 App 主進程,而是隔離在一個多帶帶進程中,然后兩個進程通過 tcp 連接進行通信...
閱讀 2797·2023-04-25 23:08
閱讀 1583·2021-11-23 09:51
閱讀 1564·2021-10-27 14:18
閱讀 3115·2019-08-29 13:25
閱讀 2831·2019-08-29 13:14
閱讀 2895·2019-08-26 18:36
閱讀 2193·2019-08-26 12:11
閱讀 811·2019-08-26 11:29