Convert a shallow cloned/pulled git repository to a normal one

Shallow clone/pull is very useful to speed up the clone process and save disk space and our time, but sometimes we may want to make a repository un-shallow in future. Re-clone/pull it all is not a good idea, in fact, git provides unshallow parameter since version 1.8.2.1

--unshallow

If the source repository is complete, convert a shallow repository to a complete one, removing all the limitations imposed by shallow repositories.

If the source repository is shallow, fetch as much as possible so that the current repository has the same history as the source repository.

https://git-scm.com/docs/git-fetch/

So next time, try git fetch --unshallow to make the repo be a normal, unshallow one, don’t just re-clone/pull.

善用 Git 的 sparse checkout 跟 shallow clone/pull 來提高工作效率

當初也是因為在摸cdnjs才開始接觸到的東西,不過貌似大家平常用不太到,所以很多人不知道有這樣的功能,也是做個筆記,有人問的時候可以直接丟這篇 …

先講shallow clone/pull:

man git-clone理面的說明:

–depth
Create a shallow clone with a history truncated to the specified number of revisions.

簡單來說就是把太久以前不需要的歷史給丟掉,大於給定數量以前的commit紀錄就會被忽略,進而省下clone時頻寬、空間及時間,這點在數千到數萬個commits以上的repository理面效果會非常明顯,像travis-ci在做CI build的時候預設的clone depth就是50,很久以前是100,缺點除了git log只看的到一定數量的提交紀錄外,git blame跟bi-sect等會需要trace先前紀錄的功能都會變的不可靠或不可用就是了。

另外一個就是sparse-checkout了,這個功能的作用是只checkout出我們想要的檔案,以cdnjs為例,.git資料夾也才600多MB而以,可是整個專案的資料夾卻高達13GB左右,由於理面的檔案大多是非常容易壓縮的source code(文字檔),所以就會有.git資料夾明明占用很少空間,可是實際上整個專案占用的空間卻非常龐大的現象,而這麼大的專案,很可能會有檔案系統操作的效率低落的問題(尤其在rebase等操作),在我們已知只需要取得某專案某些目錄或檔案的情況下,根本沒必要把所有檔案都checkout出來,這時候就可以使用sparse-checkout,在送pull request到不是自己常態性參與的專案時很好用!

用法大概是這樣(步驟3~5順序可換):

  1. 建立一個空的git專案:
    $ git init new.cdnjs && cd new.cdnjs

  2. 在專案裡面啟用sparse-checkout
    $ git config core.sparseCheckout true

  3. 設定你要checkout哪些檔案(直接寫到.git/info/sparse-checkout,多個規則可寫多行),例如我只要ajax/libs/jquery/底下的所有檔案
    $ echo '/ajax/libs/jquery/*' >> .git/info/sparse-checkout

  4. 設定remote(要從哪裡clone/pull?)
    $ git remote add origin git://github.com/cdnjs/cdnjs.git

  5. 然後就可以開始pull了(這邊可以加上前面說的shallow pull,加上–depth=n)
    $ git pull origin master

到這邊就結束了,整個專案所占用的空間應該會小非常多,這邊以jquery搭配shallow clone depth=10為例,看一下空間使用:
$ du -d 1 -h

18M ./ajax
587M ./.git
605M .

總共605MB而已

而原本的長這樣:
$ du -d 1 -h

682M ./.git
43M ./scratch
16M ./node_modules
12G ./ajax
24K ./test
32K ./build
13G .

cdnjs_github_sparsecheckout_comparasion
高達13GB …

摁 … 少了12GB的checkout快很多啊 …

如果之後想改變要checkout的檔案呢?

就直接更改專案底下的.git/info/sparse-checkout檔案,改好之後做一次git reset –hard即可
(記得更改之前確認沒有未儲存的修改即可)

範例:

/ajax/libs/jquery/*
/build
/CONTRIBUTING.md
/MIT-LICENSE
/README.md
/sparseCheckout.md
/auto-update.js
/circle.yml
/CONTRIBUTING-WIP.md
/package.json
/update-script.sh

有一點要注意就是檔名前面代表專案根目錄的斜線不要省略,若非要checkout所有同名檔案,就要把完整路徑寫清楚,例如/package.json如果寫成package.json,則所有的package.json都會被checkout出來