第27章 使用HTTP协议
HTTP协议是版本控制非常重要的一种协议,具有安全(使用HTTPS的情况下)、方便(可以跨越防火墙)等优点。Git在1.6.6版本之前对HTTP协议的支持有限,是哑协议,访问效率低,但是在1.6.6之后,通过一个CGI实现了智能的HTTP协议支持。
27.1 哑传输协议
在Git 1.6.6之前,若要通过HTTP协议提供Git服务,简单到直接拷贝Git版本库到Web服务器中就可以了,即将Git的裸版本库(不带工作区)作为一个Web静态目录直接开放给用户即可[1]。
1.只读的HTTP哑协议
如下的Apache配置,提供了Git版本库的只读访问服务:
Alias/git/path/to/repos
<Directory/path/to/repos>
Options FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
</Directory>
当用户执行git clone http://server/git/myrepo.git时,实际访问的是服务器端/path/to/repos/myrepo.git路径中的版本库。
以Web服务器静态目录方式提供Git服务,对Git版本库有一个特别的要求,即版本库目录下必须存在两个索引文件。其中一个是文件.git/info/refs,包含了版本库中所有引用的列表,且包含引用对应的SHA1哈希值。另外一个文件是.git/objects/info/packs,包含了所有打包文件的路径,以便在对象库打包后,能够通过该索引文件找到打包文件。
这是因为在Web哑协议下,作为客户端的Git类似于一个Web浏览器,远程的Web服务器只提供Git版本库文件的静态访问,而不像其他Git智能服务器那样能够提供帮助以获取Git版本库的引用和对象库文件。即作为Web客户端的Git仅凭一己之力主动到服务器上抓取文件。一旦严格配置的Web服务器禁止目录浏览(最安全和最常用的配置),如果不通过事先约定的索引文件(.git/info/refs和.git/objects/info/packs文件),Git作为Web客户端是无法获得版本库的引用列表和打包文件列表的。
在Git版本库中创建这两个索引文件很简单,只要执行git update-server-info命令即可。但是要随着版本库的更新不断地维护.git/info/refs和.git/objects/info/packs这几个文件,以便使用哑协议的Git客户端始终能够正常地访问Git版本库可不是一件简单的工作。幸好Git提供了钩子脚本扩展机制,可以实现随着Git版本库的更新同步地更改这几个文件。
在版本库的钩子脚本目录.git/hooks中,创建一个名为post-update的钩子脚本。实际上在钩子脚本的目录中已经存在一个示例脚本post-update.sample,直接将其重命名为post-update,并将其设置为可执行即可。脚本post-update非常简单,内容如下:
!/bin/sh
exec git update-server-info
2.可读写的HTTP哑协议
上面配置的HTTP哑协议只提供Git版本库的只读访问,如果需要提供可写的Git版本库服务,即允许远程客户端推送,那就还需要在Apache中为版本库逐一启用WebDAV支持。例如Apache中的配置如下:
Alias/git/path/to/repos
<Directory/path/to/repos>
Options FollowSymLinks
AllowOverride None
Order allow,deny
allow from all
</Directory>
<Location/git/myrepos.git>
DAV on
AuthType Basic
AuthName "Git"
AuthBasicProvider file
AuthUserFile/path/to/file/passwd
AuthGroupFile/path/to/file/group
Require group git
Satisfy All
</Location>
无论是只读还是支持写入,以HTTP哑传输协议配置的Git服务器都有着非常明显的缺点:
(1)数据传输效率低。当版本库经过整理,各个零散的提交文件被打包后,只获取某一个或某几个提交也需要对整个打包文件进行传输!
(2)传输过程无进度显示。哑协议在Git操作过程中不能像其他协议那样显示进度,在操作大的版本库时非常不便。
(3)为版本库提供写操作需要对每个版本库进行单独配置。缺乏类似Subversion的WebDAV插件,使得需要为每个Git库逐一进行设置。
(4)需要在服务器端手工创建版本库,而不能通过远程推送操作来实现在客户端发起版本库的创建。
(5)Git客户端不像Subversion那样提供口令缓存机制,如果要避免每次操作时频繁地输入口令,需要在URL中记录明文口令。
git clone https://username:password@server/path/to/repos/myrepo.git
下面将要介绍的智能HTTP协议则没有上面所述的大多数1、2和3缺点,在很大程度上完善了在HTTP协议上架设Git版本库的用户体验。
[1]实际上还需要执行git update-server-info命令,以更新版本库中的几个索引文件。