本地 git 的 partial clone
partial clone 是git的一项旨在减少空间和网络带宽占用的特性。它会跳过下载那些可能不会用到的git对象,而是仅仅在需要时才去下载。对于网络延迟较低且带宽不愁的用户来说,这样做往往会节省掉不少不必要的磁盘空间占用,而代价是可能失去离线访问的能力。除此之外,有些操作,例如 git blame 或者 git log -p 很可能会需要与服务器交互,从而会变得略慢一些。
比较有用的场景是在使用某些历史比较久,或是对文件整体替换较多,而大部分情况下只关注最新版本的代码库。与较早的 --depth 1 相比,partial clone的优点在于想要访问历史时仍然可以像正常的clone一样访问。
今天闲来无事打算把机房的服务器稍微升级一下,于是顺手弄了一下partial clone,稍微记一笔作弊条。
服务器
要使用此特性,服务器必须支持 Git wire protocol v2。这个新版的协议是 几年前 Brandon Williams在Google时设计并实现的,现时的git版本都应该已经支持了。
其次是服务器必须允许客户端发起filter(此特性是在git 2.19时引入的)请求。默认情况下,git服务器并不允许这样做,因为带filter的请求会产生比不带filter的请求消耗更多CPU。
启用filter的支持的方法是在服务器端将对应的库的 uploadpack.allowFilter 设置为 true,例如:
$ git config uploadpack.allowFilter true客户端
客户端比较简单,只要在 git clone 时指定 --filter=blob:none 就可以了。
效果
以FreeBSD的源代码为例,使用 --filter=blob:none 时, .git需要占用553MB的空间,而不使用的话则需要1.3GB。
其他替代方案
限制复制代码库时的历史深度(depth)
使用 --depth 1 可以达到节约空间的效果。以同一代码库为例,其 .git只需261MB的空间,但需要说明的是这样一来历史是无法访问的,假如未来需要从其他分支去cherry-pick的话,需要做一次 fetch --unshallow。
使用worktree
如果本地已经有一份clone,那么用 worktree 可能是比较理想的方案。不过,worktree要求owner是同一个人,并且对分支的使用有一些限制。假如本地的另外一份clone是只读的话,这个会比较不方便。我个人在本地的开发通常会使用worktree。