传输协议
大约 2 分钟
Git 可以通过两种主要的方式在版本库之间传输数据:“哑(dumb)” 协议和 “智能(smart)” 协议。
# 哑协议
哑协议是一个基于 HTTP 协议的只读版本库,已经很少用到了。
在传输过程中,服务端不需要有针对 Git 特有的代码;抓取过程是一系列 HTTP 的 GET 请求,这种情况下,客户端可以推断出服务端 Git 仓库的布局。所以使用哑协议的版本库很难保证安全性和私有化,所以现在基本很少使用到了。
“哑协议”的只读限制是因为其服务端没有一个 Git 的守护进程在持续的关注“客户端”的所需并与之关注,所以只能“客户端”去发起请求获取远程的变更。
# 智能协议
智能协议支持读写模式,效率比哑协议高,是目前最常用的传输方式。
但它需要在服务端运行一个进程,它可以读取本地数据,理解客户端有什么和需要什么,并为它生成合适的包文件。 总共有两组进程用于传输数据,它们分别负责上传和下载数据。
# 上传数据
为了上传数据至远端,Git 使用 send-pack
和 receive-pack
进程。运行在客户端上的 send-pack
进程连接到远端运行的 receive-pack
进程。
比如在我们执行 git push origin master
的时候:
- Git 会执行
send-pack
进程连接服务器,git-receive-pack
命令会立即为它所拥有的每一个引用发送一行响应。 - 你的
send-pack
进程会判断哪些提交记录是它所拥有但服务端没有的。send-pack
会告知receive-pack
这次推送将会更新的各个引用。服务端在收到请求后相应地作出成功或失败的 HTTP 响应。
# 下载数据
当你在下载数据时,fetch-pack
和 upload-pack
进程就起作用了。客户端启动 fetch-pack
进程,连接至远端的 upload-pack
进程,以协商后续传输的数据。
fetch-pack
连接远程服务器,然后upload-pack
会返回类似receive-pack
返回的内容。fetch-pack
进程查看它自己所拥有的对象,并响应 “want” 和它需要的对象的 SHA-1 值。它还会发送 “have” 和所有它已拥有的对象的 SHA-1 值。在列表的最后,它还会发送 “done” 以通知upload-pack
进程可以开始发送它所需对象的包文件。