远程代码库通常只是一个“纯仓库”(bare repository)——一个没有当前工作目录的仓库;仓库里仅仅是 Git 的数据,也就是 .git 目录里的内容。
协议
Git 可使用四种协议来传输数据:
- 本地传输
- SSH 协议
- Git 协议
- HTTP 协议
本地传输
远程仓库在该协议中就是硬盘上的另外一个目录,常见于所有成员拥有一个共享文件系统(如 NFS)的访问权等相似情形;就像这样:
$ git clone /path/to/git/project.git
要添加一个本地仓库指向 Git 项目,可以这样:
$ git remote add local /path/to/git/project.git
优点
-
简单,同时保留了现有文件的权限和网络访问权限
-
本地获取方便,比如说:
$ git pull /home/john/project
通常会比让 john 推送到服务器,然后你再从服务器获取要简单、快捷得多
缺点
远程操作困难,缺乏网络连接的便利性;如果使用远程硬盘挂载,又达不到网络连接的速度和效率
SSH 协议
Git 最常使用的传输协议,也是唯一一个同时便于读和写操作的网络协议。HTTP 和 Git 协议通常都是只读的,因此虽然二者对大多数人都可用,但执行写操作时还是需要 SSH。同时,SSH 也是一个验证授权的网络协议。
$ git clone ssh://user@server:project.git
或者不指明协议(Git 默认使用 SSH):
$ git clone user@server:project.git
甚至可以不指明用户,此时 Git 会使用你当前在本地登录的用户
优点
-
想拥有对网络仓库的写权限,基本上不可能不使用 SSH
-
SSH 本身架设很简单——其守护进程很常见
-
通过 SSH 访问是安全的,所有数据传输都是加密和授权的
-
SSH 很高效,会在传输之前尽可能的压缩数据
缺点
SSH 唯一的限制就是不能匿名访问,即使只是读取数据,也必须通过 SSH 的验证才能访问仓库。
如果是私有项目,那么 SSH 可能是你唯一需要使用的协议。
Git 协议
Git 协议有一个包含在 Git 软件包中的守护进程提供,它会监听一个类似 SSH 服务的特定端口(9418),而无需任何授权。
使用 Git 协议运营仓库,你需要创建 git-export-daemon-ok 文件——这是必要条件——除此之外没什么安全措施,要么所有人都能克隆,要么都不能。
所以 Git 协议通常不会用来进行推送,虽然你可以允许推送操作,但是没有授权机制将导致所有知道地址的人都可以推送。
优点
-
Git 协议是目前最快的协议
-
适合大访问量的公共项目,或是不需要对读取进行授权的大项目
-
传输机制和 SSH 相同(省去了加密和授权开销)
缺点
-
缺少授权机制,一般不会用作唯一的访问协议
-
假设困难,需要单独守护进程,需要定制
-
依赖 9418 端口的开放
HTTP/HTTPs 协议
使用 HTTP 或 HTTPs 协议的优美之处在于其架设的简便性,只需要把 Git 的纯仓库文件(bare repository)放在 HTTP 的文件目录下,再配置一个特定的 post-updare 挂钩(hook)就搞定了。例如:
$ 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
post-update hook 会默认运行 git update-server-info
来确保通过 HTTP 的获取和克隆工作正常;这条命令会在你用 SSH 向仓库推送时照常运行。之后可以用如下命令克隆仓库:
$ git clone http://youtaddress.com/gitproject.git
通过 HTTP 来推送也是可以的,不过会牵涉到 WebDAV 的设置,相对复杂一些,可以参考这篇文章
优点
-
易于架设,并且不占用过多服务器资源
-
可使用 SSL 签名验证(如:Github)
-
最常用的协议,基本不会受到阻碍(如:防火墙)
缺点
相对客户端效率较低,克隆和下载会花费更多时间,传输的开销也比其他协议更大
部署 Git Server
假设 Git Server,需要把一个现存的仓库导出为新的纯仓库(bare repository),即不包含当前工作目录的仓库,该仓库以 .git 结尾。
$ git clone --bare project project.git
Initialized empty Git repository in /path/to/project.git/
这个操作生成的目录几乎是空的(没有项目文件),除了一个 .git 目录数据的副本。这个副本和原来的 .git 目录非常相似,克隆操作得到的文件也是一样的。
$ git clone user@gitserver:/path/to/project.git
如果一个 SSH 用户对 /path/to/project.git
具有写权限,他就自动拥有推送权限。此时运行以下命令就会自动对该仓库加入可写的组权限:
$ ssh user@gitserver
$ cd path/to/project.git
$ git init --shared --bare
控制 SSH 链接
如果需要所有人都对仓库有写权限,那就需要使用 SSH 连接了。
虽然我们可以在服务器上给每一个人建立一个账户,但这样显然太麻烦了,也不方便管理。
更好的办法是建立一个公用的 git 账户,然后让每一个需要写权限的人发送一个 SSH 公钥保存在 git 账户的 ~/.ssh/authorized_keys
里面,这样一来所有人将通过 git 账户访问主机,而且不会影响提交的数据——访问主机的身份不会影响提交时的身份。
过程如下:
$ sudo adduser git # 创建 git 用户
$ su git # 切换到 git 用户
$ cd ~ # 前往其主目录
$ mkdir .ssh # 创建 .ssh 目录
之后,请你的同事把他们的公钥文件发送给你,然后添加到 authorized_keys 文件中:
$ cat id_rsa.john.pub >> ~/.ssh/authorized_keys
生成公钥的方法可以参见Github 提供的帮助文档
现在可以初始化空仓库了,别忘了 --bare 选项:
$ cd ~/git # 假设仓库都放在这里,没有就创建一个
$ mkdir project.git
$ cd project.git
$ git --bare init