5. 服务器上的Git (Git on the Server)
到此为至,你应该会做大部分的使用Git时的日常工作了。然而,为了在Git中做任何协作,你将需要有一个远端Git库。尽管你可以技术上上传或者下载更改到某个个人库中,这么做是不被鼓励的因为你可能会很容易弄混他们的工作,如果你不小心的话。另外,你想你的协作者可以存取库即使你的计算机是不在线的――有一个更可靠的公共库通常会很有用。因此,我们推荐的与其它人协作的方法是建立一个中间库,你们都可以存取它,向上上传以及从中下载。我们将把这个库称之为一个Git Server;但你会注意到它通常只占用很小的资源来保存一个Git库,因此,你很少需要一个整个的Server来实现这个目的。
运行一个Git server非常简单。首先,你选择用什么协议来与你的服务器通信。本章的第1部分将介绍可以的协议以及它们的优缺点。下一节将解释一些使用这些协议的典型的系统以及怎样使你的服务器支持它们。最后,我们将介绍几个宿主选择,如果你不介意把你的代码托管在别人的服务器上而且不想经历麻烦来设置和维护你自己的服务器的话。
如果你没有兴趣来运行你自己的服务器,你可以跳到本章的最后一节来看一些创建托管帐号的选择,然后接着阅读下一章,那里,我们将讨论在一个分布式源码控制环境中不同工作的细节。
一个远端库通常是一个裸库(bare repository)--一个没有工作目录的Git库。因为这个库仅只用来作为一个协作点,没有理由存在一个检出的快照在硬盘上;只有那些Git数据。在最简单的情形下,一个裸库仅只是你的项目的.git目录中的内容。
5.1 协议(The protocols)
Git可以使用4种主要的网络协议来传输数据:本地(local),安全Shell(SSH),Git以及HTTP。下面我们将讨论它们是什么以及在什么基本情况下,你会需要(或不需要)使用它们。
主要的一点是,除了HTTP协议外,所有其它这些都需要有Git安装并运行在服务器上。
- 本地协议(Local Protocol)
最基本的是本地协议(Local Protocol),在这种情况下,远端库是位于磁盘的另外一个目录中。这通常用在当你的小组的每个人都可以存取一个共享文件系统(一个NFS加载点),或者有很小的可能每个人都登录到同一个计算机上。后者可能不那么理想,因为你所有的代码库示例都存在于同一台机器上,使得灾难性丢失更有可能。
如果你有一个共享的加载文件系统,那么你可以从一个基于本地文件的库中clone,上传,下载。为了clone一个这样的库或者增加一个远端指向一个现存的项目,使用这个库的路径作为URL。例如,为了clone一个本地库,你可以运行如下一些命令:
$ git clone /opt/git/project.git
或者你可以这么做:
$ git clone file:///opt/git/project.git
如果你显式地在URL的起始指定了file:///,那么Git的操作会稍微有些不同。如果你只是指定了路径,Git试图去使用硬连接或者直接copy它需要的文件。如果你指定了file:///,则Git会触发一个过程,它会正常使用网络来传输数据它通常是一种较低效率的传输数据的方法。指定file:///前缀的主要原因是如果你想有一个库的干净copy而不考虑那些附加的参考或对象――通常从另一个版本控制系统或类似系统引入后产生的那些东西(查看第9章关于维护任务)。我们在这儿将使用正常的路径因为这么做总是会快一些。
为了增加一个本地的库到一个已经存在的Git项目中,你可以运行如下命令:
$ git remote add local_proj /opt/git/project.git
然后,你就可以从这个远端上传,下载就像我们通过网络所做的那样。
优点 (The Pros)
基于文件库的优点是它们很简单,它们使用现存的文件权限以及网络存取。如果你已经有了一个共享的文件系统,你的整个小组都可以存取它,设置一个库非常简单。你放置一个裸库的copy到无论什么地方,每个人都有共享存取权并设置好读写权限就像你为其它共享目录设置的那样。我们将在下一节讨论怎么为此目的导出一个裸库的copy:“在server上设置Git”(Getting Git on a Server)
还有一个很好用的选项用来快速地从其它人的工作库获取工作。如果和一个同事正工作在同一个项目上,他想让你检出(checkout)些东西,那么,运行一个类似git pull /home/john/project的命令通常要比他们上传到一个远端服务器而你再下载要容易。
缺点(The Cons)
这种方法的缺点是共享存取通常比基本的网络存取要难于搭建,从多个不同位置访问到服务器会更困难。如果你在家时想从你的笔记本电脑上传一些东西,你不得不加载上远端得磁盘,这会非常困难而且比基于网络得存取要慢。
另外需要提及的很重要的一点是如果你正在使用某种类型的共享加载点,它也并不是最快的选项。本地库仅只在你有一个快速的数据存取时才是快速的。位于NFS上的库通常要慢于同一个服务器上的通过SSH存取的库,它允许Git运行在每个系统的本地磁盘上。
- SSH协议(The SSH Protocol)
可能对Git来说最常用的传输协议是SSH。这是因为到Server的SSH存取已经在很多地方建好了――如果没有,它也很容易做到。SSH也是唯一的基于网络的协议,使用它你可以简单地读或些。另外两个网络协议(HTTP和Git)通常是只读的,因此,即使你可以用他们来服务于那些下层民众,你也需要SSH来服务于你自己的写命令。SSH也是一个认证网络协议,因为它是普遍存在的,它通常易于搭建和使用。
为了通过SSH来clone一个Git库,你可以指定ssh://URL 如下:
$ git clone ssh://user@server:project.git
或者,你可以不指定一些,当你没有显式指定时,Git假定使用SSH:
$ git clone user@server:project.git
你也可以不指定一个用户,Git将假定为你当前的登录用户。
优点(The Pros)
使用SSH的优点很多。首先,如果你想通过网络认证你的库的写权限,你不得不使用它。其次,SSH相对容易假设—SSH daemons非常普遍,许多网络管理员有使用的相关经验,许多OS分发中都已经支持SSH或者有工具来管理它。第三,通过SSH存取是安全的—数据数据传输都是加密的而且经过认证的。最后,就像Git和本地协议那样,SSH是高效的,它使数据在传输之前尽可能被压缩。
缺点(The Cons)
SSH的不好的一面是你不能使用匿名来存取你的库。其它人必需有通过SSH存取的权限才能存取你的机器,即使是对只读的访问而言,这使得SSH存取无助于开源项目。如果你仅只在你的企业网络内部使用它,SSH可能是你唯一需要处理的协议。如果你允许你的项目可以匿名只读存取,你将不得不给自己建立一个SSH用来上传而给别人使用其它方式下载。
- Git 协议(The Git Protocol)
下一个是Git协议。这是一个特殊的守护程序与Git包一起分发;它在一个专用的端口(9418)上监听,提供一个与SSH协议类似的服务,但绝对没有鉴权认证。为了让一个库可以通过Git协议来提供服务,你必需要创建git-export-daemon-ok文件――守护程序在没有这个文件存在时不会为这个库服务――但除此之外,就没有别的安全性了。或者一个Git库可以让所有人clone或者不可以。这意味者通常通过该协议不能上传(pushing)。你可以使能上传存取,但由于缺少认证,如果你打开了push存取权限,任何发现你项目URL的互联网上的人都可以上传到你的项目。这是非常罕见的。
优点(The Pros)
Git协议是Git可用的最快的传输协议。如果你正在服务的项目有大量的流量或者正在服务一个大型的项目,它对只读存取不需要用户认证,那么很可能你会需要设立一个Git 守护来服务于你的项目。它使用于SSH协议相同的没有加密的数据传输机制同时没有认证开销。
缺点(The Cons)
Git协议的不足之处是它缺少认证机制。通常不期望Git协议是你项目唯一的存取协议。通常情况下,你将把它和SSH存取一起来使用。SSH服务于少数的开发者,他们有上传的(写)权限而其它人则使用git://来实现只读的存取。这也可能是最难架设的协议。它必需运行它自己的守护进程这是定制化的(客户化的)――我们会在本章的Gitosis节中介绍一个这样的系统架设――它需要xinetd配置或者类似的东西,这并不总象公园散步那么简单。它也要求对端口9418的防火墙存取,这不是很多企业的防火墙允许的一个标准端口。在一个大企业的防火墙后面,这个不明确的端口通常会被阻止掉。
- HTTP/S协议 (The HTTP/S Protocol)
最后,我们有HTTP协议。漂亮的HTTP或者HTTPS协议是很容易安装起来的。基本上来说,所有你需要做的只是把一个裸的Git库放置在你的HTTP文档的根目录下并设置一个详细的post-update钩子就可以了(关于Git钩子的细节,请查看第7章)。现在,任何能访问你放置库的那个web server的人都可以clone你的库。为了允许通过HTTP到你的库的读权限,可以如下做:
$ cd /var/www/htdocs/
$ git clone --bare /path/to/git_project gitproject.git
$ cd gitproject.git
$ mv hooks/post-update.sample hooks/post-update
$ chmod a+x hooks/post-update
这就够了。缺省情况下运行合适的命令(git update-server-info)随Git一起来的post-update钩子使得HTTP获取及Clone可以正常工作。这个命令在你通过SSH上传库时运行,然后,其它人就可以通过如下方式clone库了:
$ git clone http://example.com/gitproject.git
在本特例中,我们正在使用/var/www/htdocs路径,这通常是Apache设置的,但你可以使用任何静态的web服务器—只需要把裸库放到它的路径下面。Git数据被作为基本的静态文件来处理(查看第9章了解它是怎么服务的相关细节)。
通过HTTP来进行Git来上传也是可能的,尽管这个技术的未被广泛使用,它需要你设置一个复杂的WebDAV支持。因为它很少被使用,我们不会在本书中涉及它。如果你对HTTP-push协议很有兴趣,你可以阅读一下为此目的而准备库:http://www.kernel.org/pub/software/scm/git/docs/howto/setup-git-server-over-http.txt。 关于使能Git push over HTTP的一个好消息是你可以使用任何WebDAV服务器而不需要特定的Git相关的功能。因此,如果你的web服务提供商支持WebDAV来实现web站点更新的话,你可以使用这个功能。
优点(The Pros)
使用HTTP协议好的一面是它很容易搭建。运行几个需要的就手的命令就可以让你可以给整个世界读取你的Git库的存取能力。它只需要花费几分钟就可以实现。HTTP协议也不是非常占用资源。因为它通常只是使用静态的HTTP服务器来存取所有数据,一个正常的Apache服务器平均可以服务于每秒数千个文件――即使对一个小服务器来说也很难超出负载。
你也可以通过HTTPS来存取你的库,这意味者你可以对传输的数据内容进行加密;或者你可以让每个客户使用一个特定的签名的SSL证书。通常,如果你能有这个长度,就很容易使用SSH公钥;但在你的具体案例中,使用签名的SSL证书或者其它基于HTTP的认证方法来实现通过HTTPS的只读存取可能是一个更好的方案。
另外一个好的方面是HTTP是如此普遍使用的协议,企业的防火墙通常都会允许这个端口的流量通过。
缺点(The Cons)
用HTTP来服务于你的Git库的不足之处是它对客户端相对来说效率不高。它通常在clone或者获取(fetch)时会花费更长的时间,使用HTTP通常比其它网络协议会有更多的网络消耗和传输流量。因为它并不能智能性地仅传输你需要的数据――在这些交互中,没有任何服务器端的动态工作――HTTP协议通常被称为一个哑协议(dumb protocol)。关于HTTP协议和其它协议之间效率方面的更多不同的信息,请参考第9章。