Xudifsd Rational life

如何让Git的clone实现断点续传

2012-02-10
xudifsd
git

在下载大文件时最重要的功能恐怕就是断点续传了。如果在一个网络环境十分不稳定的环境下使用git克隆一个大型代码库绝对是个痛苦的经历,一旦下载中断,之前下载的内容全都不复存在。

git提供断点续传的难处

根据git的传输协议,在使用非HTTP进行传输时客户端和服务器端会进行一个复杂的通信:首先服务器端会列出它的所有内容,然后客户端根据服务器端的提示找出自己需要哪些数据,再向服务器索取,之后服务器端再调用“git upload-pack”将客户端想要的commits进行打包并传输。整个过程比较复杂,而且传输协议也不像HTTP协议那么简单,并且最麻烦的就是git传输的不是静态文件而是动态生成的,这样就造成了git的传输很难修改成支持断点续传。

解决方法

用HTTP来获取静态的文件时使用断点续传实在是再简单不过的了,只要在HTTP头加一行RANGE属性即可。所以如果能将git的整个仓库转换成一个静态文件再使用普通的HTTP协议传输就能非常简单地实现断点续传了。

git其实有packfile这样的文件格式,这种文件会在运行“git gc”时或进行传输时生成,生成之后的文件包括了整个git所管理的全部内容,但仅仅只靠这样一个文件还是不能解决问题,因为这种文件只包含仓库中所有对象的内容和SHA1值,除此之外没有任何仓库元信息(分支,tag等)。所以就算得到了packfile也不能重建一个仓库。

但是git除了packfile外还有另外一种格式的文件:bundle,这种文件只是在packfile的基础上再包括刚刚提到的仓库的元信息,所以根据bundle文件我们可以完整地clone出一个仓库。

不过这和断点续传有什么关系呢?因为bundle可以用来将整个仓库变成一个静态文件,所以如果在服务器上创建bundle再用普通的HTTP来得到这个文件,就可以重创整个仓库,这也是android仓库的做法。不过这个方法需要服务器端提供clone.bundle文件,一旦服务器提供不一样的文件名这样的方法就失效了。而且这样的方法需要用户对服务器有控制权,如果不能控制服务器这一切都是空谈。一般用户常常只是在github这样的网站托管仓库,或者想要克隆一个Linux内核代码,这样只要服务器端不提供bundle,就算用户知道有这个东西也不能利用它来进行断点续传。不过为何不让别人帮你创建bundle呢?最终的解决方案就是这个网站,它接受你提供的代码仓库的url,之后它会将你想要的仓库克隆并创建一个bundle文件,之后你只需从该服务器上下载静态的bundle文件即可。下载完整个bundle文件后根据这里的举例就能得到整个仓库了,不过之后需要使用“git remote”修改一下远程仓库的地址,修改完后为了确保仓库内容最新最好还要执行一下“git pull”。


上一篇 程序的退出码

Comments

Content