## 10.6 传输协议
### 10.6.1 哑协议
哑协议一般用于架设一个基于 HTTP 协议的只读版本库。在使用哑协议拉取一个远程库的过程:
* 拉取`info/refs`文件,从而得到了一个远程引用和 SHA-1 值的列表。
* 拉去 `HEAD` 文件,确定 HEAD 引用是什么。
* 开始遍历处理,拉去 `info/refs`文件中所提到提交对象。对于每个提交对象,要再获取两个对象,一个是树对象和父提交。
* 然后拉取索引文件,它列出了这个包文件所包含的所有对象的 SHA-1 值,和该对象存在于包文件中的偏移量。
* 最后需要拉取包文件。
哑协议虽然很简单但效率略低,且它不能从客户端向服务端发送数据。
### 10.6.2 智能协议
**上传数据**
为了上传数据至远端,Git 使用`send-pack`和`receive-pack`进程。 运行在客户端上的`send-pack`进程连接到远端运行的`receive-pack`进程,`send-pack`进程会通过 SSH 连接服务器。在上传数据时,Git 会为每一个将要更新的引用发送一行数据,包括该行长度,旧 SHA-1 值,新 SHA-1 值和将要更新的引用。接下来,客户端会发送一个包文件,它包含了所有服务端还没有的对象。 最后,服务端会以成功(或失败)响应。
**下载数据**
`fetch-pack`和`upload-pack`进程用于远程下载数据,客户端启动`fetch-pack`进程,连接至远端的`upload-pack`进程,以协商后续传输的数据。在一个服务端收到一个新的拉取请求时,Git 会为每一个将要更新的引用发送一行数据,包括该行长度,旧 SHA-1 值,新 SHA-1 值和将要更新的引用。然后`fetch-pack`进程查看它自己所拥有的对象,并响应 “want” 和它需要的对象的 SHA-1 值。 它还会发送“have”和所有它已拥有的对象的 SHA-1 值。 在列表的最后,它还会发送“done”以通知`upload-pack`进程可以开始发送它所需对象的包文件:
```
003cwant ca82a6dff817ec66f44342007202690a93763949 ofs-delta
0032have 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
0009done
0000
```
- 介绍
- 第一章 起步
- 1.1 关于版本控制
- 1.2 Git 简史
- 1.3 Git 基础
- 1.4 命令行
- 1.5 安装 Git
- 1.6 初次运行 Git 前的配置
- 1.7 获得帮助
- 第二章 基础
- 2.1 获取仓库
- 2.2 记录每次更新到仓库
- 2.3 查看提交历史
- 2.4 撤销操作
- 2.5 远程仓库的使用
- 2.6 打标签
- 2.7 Git 别名
- 第三章 分支
- 3.1 分支简介
- 3.2 分支的新建与合并
- 3.3 分支管理
- 3.4 分支开发工作流
- 3.5 远程分支
- 3.6 变基
- 第四章 服务器上的 Git
- 4.1 协议
- 4.2 在服务器上搭建 Git
- 4.3 生成 SSH 公钥
- 4.4 配置服务器
- 4.5 Git 守护进程
- 4.6 Smart HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 第三方托管的选择
- 第五章 分布式 Git
- 5.1 分布式工作流程
- 5.2 向一个项目贡献
- 5.3 维护项目
- 第六章 GitHub
- 6.1 账户的创建和配置
- 6.2 对项目做出贡献
- 6.3 维护项目
- 6.4 管理组织
- 6.5 脚本 GitHub
- 第七章 Git 工具
- 7.1 选择修订版本
- 7.2 交互式暂存
- 7.3 储藏与清理
- 7.4 签署工作
- 7.5 搜索
- 7.6 重写历史
- 7.7 重置揭密
- 7.8 高级合并
- 7.9 Rerere
- 7.10 使用Git调试
- 7.11 子模板
- 7.12 打包
- 7.13 替换
- 7.14 凭证存储
- 第八章 自定义 Git
- 8.1 配置 Git
- 8.2 Git 属性
- 8.3 Git 钩子
- 8.4 使用强制策略的一个例子
- 第九章 Git 与其他系统
- 9.1 作为客户端的 Git
- 9.2 迁移到 Git
- 第十章 Git 内部原理
- 10.1 底层命令和高层命令
- 10.2 Git 对象
- 10.3 Git 引用
- 10.4 包文件
- 10.5 引用规格
- 10.6 传输协议
- 10.7 维护与数据恢复
- 10.8 环境变量
