Gitolite轻松部署/管理git server
对于今天越来越受欢迎的Git,相信做开发的朋友都基本有所耳闻。它最大的便利就是分布式的开发库,让使用git作为源码管理库的开发者可以在本地提交代码的修改而不用提交到远程的库,同时需要和团队协作、同步代码时,也仅仅是多一条指令而已。如果你想了解git的全貌,可以看《Pro git》,他有中文版,貌似没有维护到最近的,需要的可以google it。
Git 使用者的日常流程:
- 从git server远程库上clone一个副本到本地库(git clone),
- 本地开发,然后本地提交修改(git add 改动的文件;git commit 提交);无限循环这个周期。
- 第3、4步是和服务器同步。先把远程库的改动抓下来,本地解决版本合并有问题的地方(git pull)
- 然后把合并后的本地代码库提交到远程库(git push);按你的团队计划,也许每天一次。
- 另外,user除了与服务器同步外,也可以与其他协作者直接同步;如上图左和中间的头像标示。
以下介绍的,是使用gitolite管理git server,进行源代码的团队协作。本文的读者最好有linux的经验。
Gitolite介绍
其实,每一个Git库只需要–bare -shared就可以简单实现类似共享代码库服务器的功能,在git的世界,代码都是自由share的,每个人扮演的角色,和linux系统赋予这个用户的权限有关。但如果采用这种SSH authorized_keys的方式,直接系统通过shell进行 git clone的方法,会缺少了一项很必须的权限管理——每个用户对某个repository中所有项目均拥有完整的读写权限(可通过linux系统的权限设定,但依然麻烦),如果在一些大项目,涉及到多种角色权限,并要指定访问路径时,直接管理authorized_keys的方式,就显得力不从心,试想一下如果你要管理超过1000号人的authorized_keys?
Gitolite,是一套用来管理 authorized_keys 文件的,为git server实现了细粒度的访问控制的perl脚本。它的官方网址是: http://github.com/sitaramc/gitolite,起先,gitolite受到gitosis的影响而开发,其命名就是gitosis+lite的意思,轻量版的gitosis,目标是打造比gitosis更人性化和更稳定的软件套件。如今,gitolite不仅早已超过它的前辈gitosis,还占据了众多大型开源社区的一席之地,由它为git server管理着代码仓库的ACL,其中包括Fedora社区(管理着超10000个仓库)、KDE社区、Gentoo社区、MeeGo社区以及Kernel.org。Gitolite进行用户管理和访问控制设定的方法,是通过管理一个指定的 Git 仓库来实现。你只需要在这个指定的仓库内做好相应的设定,然后推送到服务器上,Gitolite就会随之改变运行策略。
Gitolite安装步骤
gitolite的安装其实非常简单,官方网址上给出的quick install仅仅4步,需要的可以看这里。另外,gitolite也有多种安装模式,例如
- 使用安装包自动安装; apt-get install / yum install
- 使用root帐号手动安装为全局应用,这样每一个服务器上的用户都可以开设代码仓库;
- 或手动在指定的普通用户帐号下安装。
以下的安装使用上述第三种方法,这样会最小程度“污染”你的server运行环境,并且能随时更新到最新版本的gitolite。
安装环境
- 假设我们现在有两台机器,server and client;
- 我们指定管理git server的管理员叫sunny;
- 并有一个普通的client user帐号jacob
下面的步骤,只是step-by-step的how-to,没有太多的why,如果要详细研究,请看gitolite的官方文档,或蒋鑫的编著《git权威指南》。
另外,gitolite的安装,会依赖git,如果你的服务器上还没安装git套件,请先自行安装。
for deb系: apt-get install git-core 或 apt-get install git
for RH系: yum install git
步骤
1.
先登录到服务器,让root新建一个gituser帐号,因为我们希望源代码仓库放在服务器的普通帐号下:
root@server# adduser --system --shell /bin/bash --group gituser
2.
给用户gituser设定密码,在SSH公钥建立后可以把这个密码禁掉
root@server# passwd gituser
3.
管理员在本地创建一个ssh key pair对
sunny@client$ ssh-keygen
如果你不想影响本机现有的一些key pair,可用-f参数
sunny@client$ ssh-keygen -f sunny_key
4.
推送管理员的公钥到remote server
sunny@client$ ssh-copy-id -i ~/.ssh/id_rsa.pub gituser@server
如果是用带有-f参数生成的,注意这里要指向正确的文件
5.
以gituser用户身份登录到服务器上
sunny@client$ ssh gituser@server
6.
执行
gituser@server$ mv .ssh/authorized_keys sunny.pub
7.
下载源码安装,或自动安装;推荐源码安装,也就三个命令;如install时候提示git版本too old, 可以下载旧版本的gitolite,例如2.1的,或者1.5.9之后的,如需要下载旧版本,点击这里
gituser@server$ git clone git://github.com/sitaramc/gitolite #下载源码 gituser@server$ gitolite/src/gl-system-install #如果提示git too old,请下载旧版本的gitolite gituser@server$ gl-setup -q ~/sunny.pub
执行gl-setup时几点注意:
- gl-setup要放到$PATH,请确定~/bin已放在PATH变量,如没有,请编辑~/.bashrc,最后面添加
PATH=~/bin:$PATH
并执行以下命令生效:
sh ~/.bashrc
- 旧版本的gl-setup,没有-q参数,如使用旧版本gitolite(例如1.5.9),直接赋参数即可
gituser@server$ gl-setup ~/sunny.pub
8.
直接package管理工具安装 (如不需要的请跳过)
gituser@server$ sudo apt-get install gitolite 或 gituser@server$ sudo yum install gitolite
如果不能sudo,请登录到root帐号再执行安装
Gitolite的管理及权限设定
gitolite的管理,包括用户管理和代码库管理,都是通过操作一个指定名称的库来实现:gitolite-admin仓库。因此gitolite的管理员sunny需要先把这个库抓到本地,进行必要的配置后,再push到remote 服务器,让设定生效:
• 抓取gitolite-admin仓库到本地
sunny@client$ git clone gituser@server:gitolite-admin
sunny@client$ cd gitolite-admin # 进入该目录,准备进行操作
1. 新增用户
- 先要获取待加用户(jacob)的pubkey,如果不知道怎么获取,请让jacob参考上述第三步生成他自己的id_rsa.pub
- sunny 把用户jacob的pubkey,放到gitolite-admin/keydir目录,并重命名为jacob.pub
... # 前提是sunny通过email、QQ、MSN等任意的方法,获取了jacob的pubkey并放到了keydir目录 # 此例中,jacob给过来的是pubkey是id_rsa.pub,如果给来的是jacob.pub则跳过这步 sunny@client:~/gitolite-admin/keydir$ mv id_rsa.pub jacob.pub
- 执行add, commmit, push进行推送,即可
sunny@client:~/gitolite-admin$ git add . sunny@client:~/gitolite-admin$ git commit -m "add jacob pubkey" sunny@client:~/gitolite-admin$ git push
- 此时jacob已增加到gitolite,但是,除了系统自带的testing库外,他操作不了其他的库
2. 新增并设定代码库
现在要在remote server新建一个代码仓proj,依然是对gitolite-admin进行配置
- 编辑gitolite-admin/conf/gitolite.conf,仿照以后的库的格式,添加:
repo proj_a # 这里设定是新增库的名称 RW+ = sunny # R是读权限,W是写权限,+是包括“强制更新一个分支,删除分支和更新一个Tag”的权限 RW = jacob # 设定RW权限的人
- 执行add, commmit, push进行推送,即可
sunny@client:~/gitolite-admin$ git add. sunny@client:~/gitolite-admin$ git commit -m "add a new repo" sunny@client:~/gitolite-admin$ git push
gitolite.conf的格式其实有相当多的复杂配置(详情请看官方手册),一般来说,象以下这样的,已够几个人的开放型小团队使用,例如:
@proj_a = sunny jacob # @proj_a是分组命名,分组用@表示,可以在后面引用分组 @proj_b = sunny taylor jean # 如果有多个用户,用空格隔开 @admins = sunny @qa = elapse flora @engineers = sunny jacob taylor jean @staff = @admins @qa @engineers # 分组可以被引用 repo gitolite-admin # 这个是gitolite的管理仓库,sunny是指定可以对其进行操作的管理员 RW+ = sunny repo proj_a RW+ = @admins RW = @proj_a elapse repo proj_b RW+ = sunny RW = @engineers flora R refs/tags/ = @qa # 这里设定的,是QA这个组,对refs/tags/开头的路径的文件只有读权限 repo testing RW+ = @stall
3. 普通用户签出操作
例如jacob要把代码库checkout出来,本地修改,然后再和remote库的代码进行版本合并。这些操作是纯粹的git操作了,团队的日常开发流程,正是这样子开展。请参阅本文一开头的那副git工作流程图,以下是几种不同情况的用户签出。
- 把remote库抓取下来,然后才开始修改
jacob@client:~$ git clone gituser@server:proj_a # 项目默认放到proj_a目录 或 jacob@client:~$ git clone gituser@server:proj_a my_proj_a # 项目被下载到my_proj_a目录下
- jacob本地已有一个现成的项目proj_a正在开发,并用git在管理着,现在想share到这个项目到proj_a
jacob@client:~$ cd proj_a jacob@client:~/proj_a$ git push --all gituser@myserver:proj_a # 推送到remote server
- 如果希望在当前目录使用一个已有的库(即合并项目),那样比较复杂,要采取非常规方法,替换.git/config文件才行
jacob@client:~$ cd proj_a jacob@client:~$ vi .git/config #把远程库对应项目的.git/config文件替换过来,一般是在team member中复制过来 jacob@client:~/proj_a$ git pull # 抓取最新的项目内容
4.删除用户
管理员在本地,删除了gitolite-admin/keydir目录下对应的用户pubkey,然后执行git 的rm操作,再 commit, push推送,即可
sunny@client:~/gitolite-admin$ rm -f keydir/jacob.pub sunny@client:~/gitolite-admin$ git rm keydir/jacob.pub sunny@client:~/gitolite-admin$ git commit -m "delete a user" sunny@client:~/gitolite-admin$ git push
5. 删除代码库
gitolite没有删除repo的代码,如要删除repo,管理员要分两步走:
- 本地编辑gitolite-admin/conf/gitolite.conf,删除相关的repo代码,然后add, commit, push推送
sunny@client:~/gitolite-admin$ git add . sunny@client:~/gitolite-admin$ git commit -m "remove a repo" sunny@client:~/gitolite-admin$ git push
- 用gituser帐号或root帐号进入服务器,把gituser/repositories下相关的repo目录删除
root@server:/home/gituser/repositories$ rm -Rf proj_a.git # 库对应proj_a的目录,带.git结尾
6. 修改代码库的名字
改名,也是分两步,和上面执行删除的顺序反过来,
- 先用gituser帐号或root帐号进入服务器,cd repositories,执行移动
root@server:/home/gituser/repositories$ mv proj_a.git proj_b.git
- 回到客户端,修改conf/gitolite.conf,把old-name的地方修改为new-name,然后add, commit并push
7. 列出本人拥有权限的库
使用普通用户jacob的帐号尝试登录remote服务器即可,
jacob@client:ssh gituser@server
例如会返回:
hello jacob, the gitolite version here is 1.5.4-2+squeeze1~bpo50+1 (Debian) the gitolite config gives you the following access: R W proj_a @R @W testing Connection to 192.168.0.101 closed.
上面列出的proj_a和testing,就是用户jacob所能操作的库,并都拥有R和W的权限。
附记
如果你对ssh很熟悉的话,gitolite的安装与使用,那是问题不大的。若你对ssh和git两者都不十分了解,使用起来可能会不算顺利。本文是gitolite配置使用的step-by-step,对于配置文件gitolite.conf,以及gitolite所支持的强大权限管理、路径正则匹配、user命名空间、和gitweb整合、委托管理以及代码库镜像备份等等,都没有叙述。如果你需要这些进阶知识,推荐看官方的帮助文档,以及《gitolite构建git服务器一文》。