为什么用shallow clone(浅克隆)

对于大仓库,使用shallow clone可以极大减少克隆时间/占用空间/网络数据。还有的时候,克隆一个特别大的仓库是,你会发现,git clone到一半就失败了,原因是内存不足。—-比如kernel.org,我当时克隆时差点疯掉,VPS失败、虚拟机也失败,最后找到了git这么的功能。

我用过的场景:

  • 克隆linux.git时内存不足
  • 编译grpc时,从git克隆源码实在太慢,而且还会克隆好多子仓库,太浪费时间,最后手动浅克隆下来就很快

怎么用

在git clone时,加入参数--depth=1,例如(<git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git>),这样git只会clone当前HEAD分支的第一条commit。

我们通过git log可以看到,当前只有一条commit。

当然,可以放心,这条commit ID是和仓库里是一样的,个人猜测是在clone的过程中,只下载跟此commit相关的数据,当然可能还有更多优化,记得我clone的.git里有pak文件。

除了git clone,fetch的时候其实也可以加--depth参数。

有什么问题

这样clone的仓库,如果你只是用来查看最新内容或者直接编译那无所谓,但是如果是要像正常仓库一样操作还是有些区别的。

  • 使用了--depth克隆的仓库就是一个浅克隆的仓库,并不完整,只包含远程仓库的HEAD分支。
  • 没有远程仓库的tags。
  • 不fetch子仓库(submodules)。
  • 即使你使用gi fetch,也不能把完整仓库fetch下来(config文件可以看到,remote.origin.fetch的值是+refs/heads/master:refs/remotes/origin/master)

解决问题

只fetch其他分支

如果不需要完整仓库,只想要fetch其他的分支,比如dev

1
2
3
git remote set-branches origin dev
git fetch --depth 1 origin dev
git checkout -b dev origin/dev

我想要完整仓库

如果需要完整仓库,下面是其中一种办法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 以下两个命令效果一样,解除只能fetch一个分支的限制
git remote set-branches origin '*'
git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'
# 注意单引号,不要让shell把*扩展,所以也可以直接手动修改.git/config文件

#然后就可以fetch了,注意加参数
git fetch --unshallow

#接下来git branch -a 就可以看到仓库完整的回来了
git branch -a

* master
remotes/origin/HEAD -> origin/master
remotes/origin/dev
remotes/origin/master

补充:只fetch远程的tags

1
2
# 不用其他修改
git fetch --tags

参考

其他

  • git好像还有一个部分克隆(Partial Clone),更加灵活,不过没有使用过
  • git的还有其他相关的参数,没有深究,如--[no-]single-branch, --[no-]shallow-submodules