本地 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。