@@ -5,8 +5,8 @@ Git 可以通过两种主要的方式在版本库之间传输数据:“哑(d
5
5
6
6
==== 哑协议
7
7
8
- 如果你建立一个使用 HTTP 协议访问并且是只读的版本库,那很可能使用的就是哑协议 。
9
- 这个协议之所以被称为“哑”协议,是因为在传输过程中,服务端不需要有针对 Git 特有的代码;抓取过程是一系列 HTTP 的 `GET` 请求,这种情况下,客户端可以假定服务端 Git 仓库的布局。
8
+ 如果你正在架设一个基于 HTTP 协议的只读版本库,一般而言这种情况下使用的就是哑协议 。
9
+ 这个协议之所以被称为“哑”协议,是因为在传输过程中,服务端不需要有针对 Git 特有的代码;抓取过程是一系列 HTTP 的 `GET` 请求,这种情况下,客户端可以推断出服务端 Git 仓库的布局。
10
10
11
11
[NOTE]
12
12
====
@@ -23,15 +23,15 @@ $ git clone http://server/simplegit-progit.git
23
23
----
24
24
25
25
它做的第 1 件事情就是拉取 `info/refs` 文件。
26
- 这个文件是通过 `update-server-info` 命令生成的,这也解释了在使用HTTP传输时,为什么必须把它设置为 `post-receive` 钩子 :
26
+ 这个文件是通过 `update-server-info` 命令生成的,这也解释了在使用HTTP传输时,必须把它设置为 `post-receive` 钩子的原因 :
27
27
28
28
[source]
29
29
----
30
30
=> GET info/refs
31
31
ca82a6dff817ec66f44342007202690a93763949 refs/heads/master
32
32
----
33
33
34
- 现在,你得到了一个远端引用和 SHA 值的列表。
34
+ 现在,你得到了一个远程引用和 SHA 值的列表。
35
35
接下来,你要确定 HEAD 引用是什么,这样你就知道在完成后,什么应该被检出到工作目录:
36
36
37
37
[source]
@@ -42,15 +42,15 @@ ref: refs/heads/master
42
42
43
43
这说明在完成抓取后,你需要检出 `master` 分支。
44
44
这时,你就可以开始漫游操作了。
45
- 因为你是从 `info/refs` 文件中所提到的 `ca82a6` commit 对象开始 ,所以你的首要操作是获取它:
45
+ 因为你是从 `info/refs` 文件中所提到的 `ca82a6` 提交对象开始的 ,所以你的首要操作是获取它:
46
46
47
47
[source]
48
48
----
49
49
=> GET objects/ca/82a6dff817ec66f44342007202690a93763949
50
50
(179 bytes of binary data)
51
51
----
52
52
53
- 然后你取回了这个对象 ——这是一个在服务端以松散格式保存的对象,你是通过使用静态 HTTP GET 请求获取的。
53
+ 你取回了一个对象 ——这是一个在服务端以松散格式保存的对象,是你通过使用静态 HTTP GET 请求获取的。
54
54
你可以使用 zlib 解压缩它,去除其头部,查看提交记录的内容:
55
55
56
56
[source,console]
64
64
changed the version number
65
65
----
66
66
67
- 接下来,你还要再获取两个对象,一个是 `cfda3b`,含有我们刚刚获取的提交对象所指向内容的树对象,另一个是它的父级提交记录 `085bb3`:
67
+ 接下来,你还要再获取两个对象,一个是 `cfda3b`,含有我们刚刚获取的提交对象所指向内容的树对象,另一个是它的父提交 `085bb3`:
68
68
69
69
[source]
70
70
----
71
71
=> GET objects/08/5bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
72
72
(179 bytes of data)
73
73
----
74
74
75
- 这样就取得了你的下一个 commit 对象 。
76
- 再抓取 tree 对象 :
75
+ 这样就取得了你的下一个提交对象 。
76
+ 再抓取树对象 :
77
77
78
78
[source]
79
79
----
80
80
=> GET objects/cf/da3bf379e4f8dba8717dee55aab78aef7f4daf
81
81
(404 - Not Found)
82
82
----
83
83
84
- 噢——看起来这个树对象在服务端并不以松散格式对象存在,所以得到了 404 响应,代表在 HTTP 服务端没有找到该对象。
85
- 这有好几个可能的原因——这个对象可能在替代版本库里面,或者在打包文件里面 。
86
- Git 会首先检查任何列出的替代版本库 :
84
+ 噢——看起来这个树对象在服务端并不以松散格式对象存在,所以你得到了一个 404 响应,代表在 HTTP 服务端没有找到该对象。
85
+ 这有好几个可能的原因——这个对象可能在替代版本库里面,或者在包文件里面 。
86
+ Git 会首先检查所有列出的替代版本库 :
87
87
88
88
[source]
89
89
----
90
90
=> GET objects/info/http-alternates
91
91
(empty file)
92
92
----
93
93
94
- 如果这返回了一个替代版本库列表 ,那么 Git 就会去那些地址检查松散格式对象和文件——这是一种能让派生项目共享对象以节省磁盘的好方法。
95
- 然而,在这个例子中,没有列出可用的替代版本库。所以你所需要的对象肯定在某个打包文件中 。
96
- 要检查服务端有哪些可用的打包文件 ,你需要获取 `objects/info/packs` 文件,这里面有一个打包文件列表 (它也是通过执行 `update-server-info` 所生成的):
94
+ 如果这返回了一个包含替代版本库 URL 的列表 ,那么 Git 就会去那些地址检查松散格式对象和文件——这是一种能让派生项目共享对象以节省磁盘的好方法。
95
+ 然而,在这个例子中,没有列出可用的替代版本库。所以你所需要的对象肯定在某个包文件中 。
96
+ 要检查服务端有哪些可用的包文件 ,你需要获取 `objects/info/packs` 文件,这里面有一个包文件列表 (它也是通过执行 `update-server-info` 所生成的):
97
97
98
98
[source]
99
99
----
100
100
=> GET objects/info/packs
101
101
P pack-816a9b2334da9953e530f27bcac22082a9f5b835.pack
102
102
----
103
103
104
- 服务端只有一个打包文件 ,所以你要的对象显然就在里面。但是你要先检查它的索引文件以确认。
105
- 即使服务端有多个打包文件 ,这也是很有用的,因为这样你就可以知道你所需要的对象是在哪一个打包文件里面 :
104
+ 服务端只有一个包文件 ,所以你要的对象显然就在里面。但是你要先检查它的索引文件以确认。
105
+ 即使服务端有多个包文件 ,这也是很有用的,因为这样你就可以知道你所需要的对象是在哪一个包文件里面 :
106
106
107
107
[source]
108
108
----
109
109
=> GET objects/pack/pack-816a9b2334da9953e530f27bcac22082a9f5b835.idx
110
110
(4k of binary data)
111
111
----
112
112
113
- 现在你有这个打包文件的索引 ,你可以查看你要的对象是否在里面——因为索引文件列出了这个打包文件所包含的所有对象的 SHA 值,和该对象存在于打包文件中的偏移量 。
114
- 你的对象就在这里,接下来就是获取整个打包文件 :
113
+ 现在你有这个包文件的索引 ,你可以查看你要的对象是否在里面——因为索引文件列出了这个包文件所包含的所有对象的 SHA 值,和该对象存在于包文件中的偏移量 。
114
+ 你的对象就在这里,接下来就是获取整个包文件 :
115
115
116
116
[source]
117
117
----
118
118
=> GET objects/pack/pack-816a9b2334da9953e530f27bcac22082a9f5b835.pack
119
119
(13k of binary data)
120
120
----
121
121
122
- 现在你也有了你的 tree 对象 ,你可以继续在提交记录上漫游。
123
- 它们全部都在这个你刚下载的打包文件里面 ,所以你不用继续向服务端请求更多下载了。
122
+ 现在你也有了你的树对象 ,你可以继续在提交记录上漫游。
123
+ 它们全部都在这个你刚下载的包文件里面 ,所以你不用继续向服务端请求更多下载了。
124
124
由于刚开始下载的 HEAD 引用指向 `master` 分支,Git 会将它检出到工作目录。
125
125
126
126
==== 智能协议
127
127
128
128
哑协议虽然很简单但效率略低,且它不能从客户端向服务端发送数据。
129
129
智能协议是更常用的传送数据的方法,但它需要在服务端运行一个进程,而这也是 Git 的智能之处——它可以读取客户端数据,明确指出其有什么和需要什么,并为它生成合适的包文件。
130
- 总共有两组进程用于传输数据,分别负责上传和下载数据 。
130
+ 总共有两组进程用于传输数据,它们分别负责上传和下载数据 。
131
131
132
132
===== 上传数据
133
133
@@ -177,7 +177,7 @@ Git 会为每一个将要更新的引用发送一行数据,包括该行长度
177
177
这里的全为 '0' 的 SHA-1 值表示之前没有过这个引用——因为你正要添加新的 experiment 引用。
178
178
删除引用时,将会看到相反的情况:右边的 SHA-1 值全为 '0'。
179
179
180
- 接下来,客户端会发送一个打包文件 ,它包含了所有服务端还没有的对象。
180
+ 接下来,客户端会发送一个包文件 ,它包含了所有服务端还没有的对象。
181
181
最后,服务端会以成功(或失败)响应:
182
182
183
183
[source]
@@ -208,7 +208,7 @@ HTTPS 与 HTTP 相比较,除了在“握手”过程略有不同外,其他
208
208
=> POST http://server/simplegit-progit.git/git-receive/pack
209
209
----
210
210
211
- 这个 `POST` 请求的负载是 `send-pack` 的输出和相应的打包文件 。
211
+ 这个 `POST` 请求的负载是 `send-pack` 的输出和相应的包文件 。
212
212
服务端在收到请求后相应地作出成功或失败的响应。
213
213
214
214
===== 下载数据
@@ -243,7 +243,7 @@ $ ssh -x git@server "git-upload-pack 'simplegit-progit.git'"
243
243
244
244
这时候,`fetch-pack` 进程查看它自己所拥有的对象,并响应“want”和它需要的对象的 SHA 值。
245
245
它还会发送“have”和所有它已拥有的对象的 SHA 值。
246
- 在列表的最后,它还会发送“done”以通知 `upload-pack` 进程可以开始发送它所需对象的打包文件 :
246
+ 在列表的最后,它还会发送“done”以通知 `upload-pack` 进程可以开始发送它所需对象的包文件 :
247
247
248
248
[source]
249
249
----
@@ -281,10 +281,10 @@ $ ssh -x git@server "git-upload-pack 'simplegit-progit.git'"
281
281
----
282
282
283
283
这个输出格式还是和前面一样的。
284
- 这个请求的响应包含了所需要的打包文件 ,并指明成功或失败。
284
+ 这个请求的响应包含了所需要的包文件 ,并指明成功或失败。
285
285
286
286
==== 协议总结
287
287
288
- 这一章节是传输协议的一个基本概貌 。
289
- 传输协议还有很多其它的特性,像是 `multi_ack` 或 `side-band` 容量 ,但是这些内容已经超出了本书的范围。
288
+ 这一章节是传输协议的一个概貌 。
289
+ 传输协议还有很多其它的特性,像是 `multi_ack` 或 `side-band`,但是这些内容已经超出了本书的范围。
290
290
我们希望能给你展示客户端和服务端之间的基本交互过程;如果你需要更多的相关知识,你可以参阅 Git 的源代码。
0 commit comments