不知道大家有沒有遇到比較大的項目,git clone 很慢很慢,甚至會失敗的那種。大家會怎么處理的呢?
可能會考慮換一個下載源,可能會通過一些手段提高網(wǎng)速,但是如果這些都試過了還是比較慢呢?
今天我就遇到了這個問題,我需要把 typescript 代碼從 gitlab 下載下來,但是速度特別慢:
git clone https://github.com/microsoft/TypeScript ts
等了很久還是沒下載完,于是我加了一個參數(shù):
git clone https://github.com/microsoft/TypeScript --depth=1 ts
這樣速度提高了幾十倍,瞬間下載完了。
加上 –depth 會只下載一個 commit,所以內容少了很多,速度也就上去了?!鞠嚓P推薦:Git使用教程】
而且下載下來的內容是可以繼續(xù)提交新的 commit、創(chuàng)建新的分支的。不影響后續(xù)開發(fā),只是不能切換到歷史 commit 和歷史分支。
我用我的一個項目測試過,我首先下載了一個 commit:
然后做一下改動,之后 git add、commit、push,能夠正常提交:
創(chuàng)建新分支也能正常提交。唯一的缺點就是不能切換到歷史 commit 和歷史分支。
在一些場景下還是比較有用的:當需要切換到歷史分支的時候也可以計算需要幾個 commit,然后再指定 depth,這樣也可以提高速度。
大家有沒有想過,這樣能行的原理是什么?
git 原理
git 是通過一些對象來保存信息的:
- glob 對象存儲文件內容
- tree 對象存儲文件路徑
- commit 對象存儲 commit 信息,關聯(lián) tree
以一個 commit 為入口,關聯(lián)的所有的 tree 和 blob,就是這個 commit 的內容。
commit 之間相互關聯(lián),而 head、branch、tag 等是指向具體 commit 的指針??梢栽?.git/refs 下看到。這樣就基于 commit 實現(xiàn)了分支、tag 等概念。
git 就是通過這三個對象來實現(xiàn)的版本管理和分支切換的功能,所有 objects 可以在 .git/objects 下看到。
這就是 git 的原理。
主要理解 blob、tree、commit 這三個 object,還有 head、tag、branch、remote 等 ref。
能下載單個 commit 的原理
我們知道了 git 是通過某一個 commit 做為入口來關聯(lián)所有的 object,那如果我們不需要歷史自然就可以只下載一個 commit。
這樣依然基于那個 commit 創(chuàng)建新的 commit,關聯(lián)新的 blob、tree 等。但是歷史的 commit、tree、blob 因為都沒有下載下來所以無法切回去,相應的 tag、branch 等指針也不行。這就是我們下載了單個 commit 卻依然可以創(chuàng)建新的分支、commit 等的原理。
總結
遇到大的 git 項目的時候,可以通過添加 –depth 參數(shù)使得速度極大提升,歷史 commit 越多,下載速度提升越大。
而且下載下來的項目依然可以進行后續(xù)開發(fā),可以創(chuàng)建新的 commit 和新的分支、tag,只是不能切換到歷史 commit、分支、tag。
我們梳理了 git 的原理:通過 tree、blob、commit 這三個 object 來存儲文件和提交信息,通過 commit 之間的關聯(lián)來實現(xiàn)分支、標簽等功能。commit 是入口,關聯(lián)所有的 tree 和 blob。
我們下載了一個 commit,就是下載了他關聯(lián)的所有 tree、blob,還有一些 refs (包括tag、branch 等),這就是 –depth 的原理。
希望大家在不需要切換到歷史 commit 和分支的場景下可以用這個技巧來提升大項目的 git clone 速度。