Git--服务器篇


  本系列将通过三篇文章:Git–客户端,Git–服务器,Git–底层原理。三个方面来介绍Git的基础用法,窍门技巧和以及其实现原理。

协议

  上一篇Git–客户端,介绍了Git的使用方法。我们知道了远程仓库这个概念,这个远程仓库就是“Git 服务器”。Git可以使用4种协议传输数据:本地协议、Git协议、SSH协议和HTTP(S)协议。

本地协议

  你可以在自己的电脑上创建本地Git仓库,在本机进行克隆,推送和抓取。要从本机仓库克隆或者将其作为远程仓库添加到工程里,可以用指向改仓库的路径作为URL。比如下面两种方式:

1
2
3
$ git clone /path/git/project.git
#
$ git clone file://path/project.git

  这两种方式是不同的。如果使用了”file://“,Git会调用它平时通过网络来传输数据的工序,而这种方式的效率相对很低。使用 file:// 前缀的方式可以创建一个不包含无关引用或对象的干净仓库副本,比如从其他版本控制导入。通常使用普通路径,因为一般情况下这样总是更快。
  本地协议的优点在于简单,一些开发工具就支持在创建项目的同时创建本地仓库(比如Xcode)。这个也是从别人的工作目录里获取数据的快捷方法。直接从对方仓库获得,就不需要对方将数据推送到服务器,然后你再从服务器获得。当然。这种方式也是有缺点的。比如你在公司机器上创建了仓库,若是在家要访问这个仓库,就要先挂载远程硬盘这和基于网络连接的访问相比更加困难和缓慢。而且在同一个服务器上,如果二者同时允许 Git 访问本地硬盘,通过 NFS 访问仓库通常会比SSH慢。下面我们就来说说SSH。

SSH协议

  通过SSH克隆一个Git仓库可以像下面这样给出ssh://的URL,或不指名协议名称。这时Git会默认使用SSH。也可以不指名用户,Git会默认使用当前用户。

1
2
3
$ git clone ssh://user@server:project.git
#
$ git clone user@server:project.git

  SSH是唯一一个同时便于读和写操作的网络协议。另外两个网络协议 (HTTP 和 Git)通常都是只读的,所以虽然二者对大多数人都可用,但执行写操作时还是需要SSH。SSH同时也是一个验证授权的网络协议;而因为其普遍性,通常也很容易架设和使用。
  使用SSH有很多的好处。首先要对仓库进行写权限,就需要使用SSH,然后SSH的假设比较简单,再次,使用SSH进行访问是安全的(传输数据经过加密和授权),最后,SSH很高效,会在传输之前尽可能的压缩数据。当然SSH也有一些缺点,比如不能通过它实现仓库的匿名访问。即使仅为读取数据,也必须在能通过SSH访问主机的前提下才能访问仓库,这使得SSH不利于开源的项目。如果想允许对项目的匿名只读访问,那么除了为自己推送而架设SSH协议之外,还需要其他协议来让别人获取数据。

Git协议

  Git协议是一个包含在Git软件包种的特殊的守护进程,它会监听一个提供类似于SSH服务的特定端口(9418),而不需任何授权。Git协议是目前最快的协议,它使用与SSH相同的传输机制,但是省去了加密和授权步骤。使用Git协议管理仓库,需要创建git-export-daemon-ok文件,它是Git协议进程提供仓库服务的必要组件,但该服务没有什么安全措施。要么所有人都能克隆Git仓库,要么谁也不能。这代表该协议通常不能用来进行推送。你可以允许推送操作,但是由于没有授权机制,一旦允许该操作,网络上任何一个知道项目 URL 的人将都有推送权限。这是非常危险的。

HTTP/S 协议

  最后是HTTP/S协议。HTTP/S协议便于假设,只需要把Git文件放在HTTP的文件目录下,配置一个特定的post-update(hook),就可以了。

1
2
3
4
5
$ cd /var/www/htdoc
$ git clone --bare /path/to/git project.git
$ cd project.git
$ mv hooks/post-update.sample hooks/post-update
$ chomd a+x hooks/post-update

  成功以后,就可以使用HTTP协议来操作仓库了:

1
$ git clone http://path/project.git

  HTTP/S协议的好处是便于架设,使用HTTPS协议可以加密传输内容,也可以要求客户端使用特定签名的SSL证书。HTTP作为常见的协议,企业级的防火墙一般也允许其通信的端口。但HTTP/S协议也有不好的一面,首先是传输体积大,因为传输过过程中没有服务端的动态计算,所以效率可能会有些低。

部署Git

  开始架设Git服务器,需要先把一个现存的仓库导出为新的仓库(不包含当前工作目录的仓库)。把一个仓库克隆为纯仓库,可以使用git –bare选项,纯仓库的目录以.git结尾:

1
$ git clone --bare your_project your_project.git

  有了仓库的纯副本以后需要把这个副本放在服务器上,并设定相关的协议。假如一个域名为 git.example.com的服务器已经架设好,应可以通过SSH访问,而你想要把Git仓库存储在/opt/git目录下,只需要下面的操作:

1
$ scp -r your_project.git user@git.example.com:/opt/git

  成功以后,对该服务器有SHH访问权限并能读写/opt/git的用户就可以操作该仓库。比如克隆:

1
$ git clone user@git.example.com:/opt/git/your_project.git

  如果有多人来操作这个仓库,可以在主机上建立一个Git账户,收集每个要操作仓库人的SSH公钥,然后将其加入Git账户的~/.ssh/authorized_keys 文件.这样一来,所有都可以通过git账户访问主机,由于使用不同的SSH,所以并不会影响修改对仓库的操作记录。

生成SSH 公钥

  要管理自己的SSH,首先可以先查看是否已经存在一个公钥了。SSH公钥默认存储在账户的~/.ssh 目录。

1
2
3
$ cd ~/.ssh
$ ls
# id_rsa id_rsa.pub known_hosts

  可以看到上面目录中.pub文件是公钥,另一个是密钥。假如没有这些文件(甚至没有.ssh).可以使用ssh -keygen来创建他们。成功以后可以查看.pub文件

1
2
3
4
5
6
7
8
9
$ cat ~/.ssh/id_rsa.pub
ssh-rsa vczhPaYACe3bP6Vo0Au49jDNZQpJpmJHQZIjV6NppgVW0D
+vczhPaYACe3bP6Vo0Au49jDNZQpJpmJHQZIjV6NppgVW0D
+fsx7GiWyzGPgviRiZmB9vunitM94Gy3cpRjJxyn2IcGgACe3bP6Vo0Au
49jDNZQpJpmJHQZIjV6NppgVW0DopUKP5dpQlE4IFFdMZscfdAWDR9D0G
V+NS29HsekHjPNAnpE1E1i6yjcIaiBBsgcDyP
+vczhPaYACe3bP6Vo0Au49jDNZQpJpmJHQZIjV6NppgVW0D
+6QtqlSabEL0Mh7wnpie4MHqftzdEjOK4gBXwm75CsyrRPziQZ1gcsf1T
lbi0MkN6zvyJZY7OR6yN45cmop3W1uH1H5NZAUAJ devsnow@rainbow.local

  如果需要给多个操作系统设置相同的SSH,可以参考github的帮助页面:https://help.github.com/articles/generating-ssh-keys/