目錄
1. 抽離場景---從大項目中抽離一個獨立文件夾作爲新的子項目
2.在總項目之外任一地方創建一個空項目,並通過本地項目進行動態拉取項目
推薦閱讀:爲什麼你的 Git 倉庫變得如此臃腫
可能在小白剛剛接觸git的時候,只是掌握了簡答的commit pull push clone等等的基本操作,在還沒有接觸.gitignore的時候,有時候會把一些大文件直接懟到git本地倉庫中,殊不知當時間一長久,git的項目就會逐漸變得龐大,那是一個多麼痛的領悟啊!!因此一定要摒棄杜絕這種養疽成患的習慣。
接下來就是根據自己平時的經驗總結如下幾個操作方法,對各個操作做了一次整合與記錄。實際的需求本人暫時分爲兩種。(還有哪些場景,還望各位大佬不吝賜教)
1. 抽離場景---從大項目中抽離一個獨立文件夾作爲新的子項目
2. 瘦身場景---獨立項目刪除大文件(file)/ 大文件夾(dir)
1. 抽離場景---從大項目中抽離一個獨立文件夾作爲新的子項目
此場景是因爲實際工作就是在一個項目中又有很多項目,混合開發,比如期初項目是一個javaweb項目,然而隨着業務發展,項目的開發模式開始走向前後端分離,那麼此時一些前端項目由react/vue/angular編寫,而所有後端業務邏輯由java承接,那麼有時候我們想在項目實際開發完成之後,剝離前端項目,(假設前端項目所有代碼放置於一個單獨文件夾下,或者通過重新組件一個文件夾,把這些項目放置於一個新文件夾中),那麼我們想把這個項目單獨抽離出來形成一個獨立的項目來進行單獨開發與維護,那麼我們怎麼操作。
0. 查看git大小
size-pack 爲 實際項目的大小以kb爲單位, 這裏5G大小,臥槽,這個就是一個超級大炸彈呢不是。要是在這5G文件大小中把除去只留下幾M大小的小項目,那無疑是大海撈針,太坑了。不過git給我們一個新功能,就是可以根據某個子目錄,並把子目錄相關的所有commit信息也一併抽取出來生成一個新分支,這個命令就是subtree命令
1. 查看有哪些大文件(top 10)
$ git subtree split -P ideaproject/reactapp_3d -b eapcubeweb
ideaproject/reactapp 目錄存儲的是一個以react開發的web項目 -P <=> -Project(項目的意思)
eapcubeweb 是分支名, -b <=> -branch (分支的意思)
2.在總項目之外任一地方創建一個空項目,並通過本地項目進行動態拉取項目
git pull ../頂級項目目錄 eapcubeweb 從本地git項目中拉取項目以及對應的分支,此時只會拉取相關的refs
3.查看新項目目錄大小
可以發現,我們從5G大小的大餅中,切了一小塊口子出來,生成了一個獨立的新項目,項目大小爲143M,對於一個項目來說143M顯然還是很大的,但是總比5G小太多了。我們如何進行更進一步地減少體積呢?那就是下面的將要將的瘦身活動了。
2.瘦身場景--獨立項目刪減大文件(夾)場景
此場景是因爲實際工作中會不自覺地將一些大文件或者一些敏感信息不小心直接commit到本地,後續又沒有做reset等操作(可能還不太清楚這個東西),因此大夥兒得過且過,就將就着用。那是又非常大的潛在風險的。尤其是一些敏感信息,讓我想到了bilibli泄漏事件,除去推廣成分,敏感信息往往是大家非常關注的,一旦不小心把敏感信息發佈出去,即使後期以commit重新修改方式,在有心人眼裏,還是能夠把“歷史”給扒出來看的。
0. 查看git大小
size-pack 爲 實際項目的大小以kb爲單位, 這裏143M大小
1. 查看有哪些大文件(top 10)
git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -10 | awk '{print$1}')"
1.1 查看有哪些大文件(top 10)
這個命令只能查看對應文件名hash值對應的文件類型以及文件大小,第三列單位爲字節(bytes),如下可以看到有一個非常大的文件,大致有130M左右
$ git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -10
339bc58c7c3297d62cb8e5f2adb3411d44faa9c9 blob 901183 245971 14860559
f6e40f652575246527301158499a994d8c0da2b1 blob 901308 246024 4172051
a7e358eee7ec445f98be7e0643bdd897f048dfc8 blob 952135 112106 1942204
155d47e5efca426f4acfff12a69c587d8af590f0 blob 972382 373102 150876
85254d05a2e81de8a84c699dcf9005c964cc0688 blob 3586927 1049913 6310668
edaf3cc9e3b69918c145d6fe5bb1380d8aeeb943 blob 3831516 1613712 16797794 1 3d439f7ae0fd35157badef64a99e98f7e05c58ee
9e31acb78b79e0bb9c04c368da67ea0bcb4a04f2 blob 6637186 1303181 15106530
22a4a4234b6f41738ef4f7230c2786367b1efd2a blob 6637343 1303217 4418075
3d439f7ae0fd35157badef64a99e98f7e05c58ee blob 23890168 5321790 7360581
d2fdda3d1492d397b53a11055dfb87c093950c57 blob 134474097 127995889 18592453
$ git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -10 | awk '{print$1}')"
155d47e5efca426f4acfff12a69c587d8af590f0 dist/js/echarts-all.js
a7e358eee7ec445f98be7e0643bdd897f048dfc8 undefined/css/main.86013fab.css.map
f6e40f652575246527301158499a994d8c0da2b1 undefined/js/34.ae2e8c03.chunk.js
22a4a4234b6f41738ef4f7230c2786367b1efd2a undefined/js/34.ae2e8c03.chunk.js.map
85254d05a2e81de8a84c699dcf9005c964cc0688 undefined/js/main.1599a4ca.js
3d439f7ae0fd35157badef64a99e98f7e05c58ee undefined/js/main.1599a4ca.js.map
339bc58c7c3297d62cb8e5f2adb3411d44faa9c9 dist/js/34.addd526f.chunk.js
9e31acb78b79e0bb9c04c368da67ea0bcb4a04f2 dist/js/34.addd526f.chunk.js.map
edaf3cc9e3b69918c145d6fe5bb1380d8aeeb943 dist/js/main.a2f9ed0b.js.map
d2fdda3d1492d397b53a11055dfb87c093950c57 node_modules.rar
2. git filter-branch
$ git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch node_modules.rar' --prune-empty --tag-name-filter cat -- --all
git filter-branch --index-filter 讓每個提交的文件都複製到索引(.git/index)中
然後運行過濾器命令:git rm --cached --ignore-unmatch 文件名 ,讓每個提交都刪除掉“文件名”文件
然後--tag-name-filter cat 把每個tag保持原名字,指向修改後的對應提交
最後-- --all 將所有ref(包括branch、tag)都執行上面的重寫
刪除大文件夾下的所有內容,不用一個一個刪,提高刪除效率,比如實際應用中基於nodejs開發的前端項目,往往會在npm install安裝階段生成一個node_modules目錄,這裏是存儲當前項目關聯的包,可想而知,這個文件有多大,所以我們打算刪除以及在之前版本中加入到項目中的該文件夾下面的目錄,而且我們確信,刪除這個文件夾項目下所有文件對項目本身沒有任何關係,所以可以執行下面命令:
$ git filter-branch --force --index-filter 'git rm -rf --cached --ignore-unmatch node_modules' --prune-empty --tag-name-filter cat -- --all
跟刪除大文件類似,我們需要添加-rf 遞歸循環刪除文件夾下的所有文件
3. “遍”操作第一步和第二步
重複第一步和第二步,直到自己認爲沒有垃圾文件爲止,這裏同比與編譯原理的“遍”的概念。
4. 刪除緩存下來的ref和git操作記錄
$ git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
$ git reflog expire --expire=now --all
這一步類似於jvm虛擬機中的刪除gcroot引用操作,也就是要把所有指向這個文件或目錄的記錄的引用都刪除了,方便垃圾回收機制處理垃圾。
5. 垃圾回收
上面2步把大文件的索引都切斷了,這個時候進行垃圾回收,就可以很明顯看到效果了 回收操作,.git目錄中的文件大小會立馬減少(git gc 並不會立馬看到 --prune意味着剪枝操作,也就是在在整個構造樹中減少所有文件)
6. 查看git是否減少
經過上方一頓猛如虎的操作,我們看到size-pack減少到了2m,還是略有興奮的感覺。