Skip to content

Instantly share code, notes, and snippets.

@nightire
Last active August 8, 2016 15:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nightire/5070032 to your computer and use it in GitHub Desktop.
Save nightire/5070032 to your computer and use it in GitHub Desktop.
Git on the Server

Git on the Server

远程代码库通常只是一个“纯仓库”(bare repository)——一个没有当前工作目录的仓库;仓库里仅仅是 Git 的数据,也就是 .git 目录里的内容。

协议

Git 可使用四种协议来传输数据:

  1. 本地传输
  2. SSH 协议
  3. Git 协议
  4. HTTP 协议

本地传输

远程仓库在该协议中就是硬盘上的另外一个目录,常见于所有成员拥有一个共享文件系统(如 NFS)的访问权等相似情形;就像这样:

$ git clone /path/to/git/project.git

要添加一个本地仓库指向 Git 项目,可以这样:

$ git remote add local /path/to/git/project.git

优点

  1. 简单,同时保留了现有文件的权限和网络访问权限

  2. 本地获取方便,比如说:$ 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 会使用你当前在本地登录的用户

优点

  1. 想拥有对网络仓库的写权限,基本上不可能不使用 SSH

  2. SSH 本身架设很简单——其守护进程很常见

  3. 通过 SSH 访问是安全的,所有数据传输都是加密和授权的

  4. SSH 很高效,会在传输之前尽可能的压缩数据

缺点

SSH 唯一的限制就是不能匿名访问,即使只是读取数据,也必须通过 SSH 的验证才能访问仓库。

如果是私有项目,那么 SSH 可能是你唯一需要使用的协议。

Git 协议

Git 协议有一个包含在 Git 软件包中的守护进程提供,它会监听一个类似 SSH 服务的特定端口(9418),而无需任何授权。

使用 Git 协议运营仓库,你需要创建 git-export-daemon-ok 文件——这是必要条件——除此之外没什么安全措施,要么所有人都能克隆,要么都不能。

所以 Git 协议通常不会用来进行推送,虽然你可以允许推送操作,但是没有授权机制将导致所有知道地址的人都可以推送。

优点

  1. Git 协议是目前最快的协议

  2. 适合大访问量的公共项目,或是不需要对读取进行授权的大项目

  3. 传输机制和 SSH 相同(省去了加密和授权开销)

缺点

  1. 缺少授权机制,一般不会用作唯一的访问协议

  2. 假设困难,需要单独守护进程,需要定制

  3. 依赖 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 的设置,相对复杂一些,可以参考这篇文章

优点

  1. 易于架设,并且不占用过多服务器资源

  2. 可使用 SSL 签名验证(如:Github)

  3. 最常用的协议,基本不会受到阻碍(如:防火墙)

缺点

相对客户端效率较低,克隆和下载会花费更多时间,传输的开销也比其他协议更大

部署 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment