GIT系列一:使用gitolite搭建git仓库管理服务


当在工程实践中需要频繁使用git后发现,要达到真正的熟练掌握git并不是学会几个简单的git commit, git push 就能搞得定的。
因此开了这样一个系列,来集中梳理各种正确运用git及相关服务的要点。
不过既然是梳理,像那种直接man就能查到的简单用法就不会再赘述。重点在于梳理那些在使用git时会遇到的坑。
作为git工程实践系列的开篇,则是介绍如何使用gitolite在自己的机器上搭建git仓库管理服务。
只有在搭建好了一个良好的后台管理服务,才能为后续的git使用保驾护航。

如果是想了解git基本操作,这是一个不错的开始:[Try git](https://www.codeschool.com/courses/try-git)  

安装gitolite

// 创建专用账号
@server # adduser -m git -s /bin/bash

// 将客户端公钥上传服务器
@admin-client # scp ~/.ssh/id_ras.pub git@gitolite-server-ip:/home/git/admin.pub

// 切换到专用账号git,然后安装gitolite
# sudo su git
$ mkdir -p ~/bin
$ cd /home/git
$ git clone git://github.com/sitaramc/gitolite    // 获取gitolite
$ git checkout -b newest-release v3.6.3           // 换到最新的一次release
$ gitolite/install -ln ~/bin             // 安装gitolite到指定目录

// 配置管理员公钥
$ bin/gitolite setup -pk admin.pub

克隆gitolite

至此可在admin-client克隆gitolite管理仓库

@admin-client # git clone git@gitolite-server-ip:gitolite-admin

    // MAC电脑下如果是新生成的id_ras.pub,则需要添加管理
    @admin-client # ssh-add -K ~/.ssh/id_ras.pub

# cd gitolite-admin
# ls
conf    keydir        // conf用于配置git项目权限,keydir用于存放git用户公钥

新建GIT项目

// 回到客户端,在gitolite的配置中,增加project项目,并设置admin访问权限
# cat conf/gitolite.conf
repo gitolite-admin
    RW+     =   admin

repo testing
    RW+     =   @all

repo git-learning
    RW+     =   admin

# 提交对gitolite配置文件的修改
# git commit -am 'add git project'
# git push origin master    // 至此,管理员可在客户端克隆git@gitolite-server-ip:project

// 新的project.git会在执行git push自动创建,默认的目录是:/home/git/repositories

新增GIT用户

// 将要添加的用户的公钥上传到gitolite-admin/kerdir目录下
$ ls kerdir/
admin.pub new.pub

// 配置用户new的权限
$ cat conf/gitolite.conf
repo gitolite-admin
    RW+     =   admin

repo testing
    RW+     =   @all

repo git-learning
    RW+     =   admin
    RW        =    new

// 然后提交
$ git add kerdir/new.pub
$ git commit -am 'add user new for project'
$ git push origin master

权限控制管理

/* 实例1 */  
repo project
    RW+        =    admin    // admin 有读,写,强制写的权限
    R        =    new        // new 仅有读权限,如果尝试提交会报错

/* 实例2 */ 
repo project
    RW+            =    admin    // admin 有读,写,强制写的权限
    // new 对所有以dev开始的分支都有读写权限。即可以新建dev3,修改dev2分支 
    RW    dev        =    new        

/* 实例3 */
repo project
    RW+            =    admin
    // new 仅对dev分支有写权限,$表示精确匹配
    RW    dev$    =    new

/* 实例4 */
repo project
    ...
    -    refs/tags/v[0-9]    = new    // new用户仅能创建除了以v加上数字开头之外的其他tag

/* 实例5 */
repo project
    ...
    // 除了根目录的Makefile文件外,new对其他文件都具有写权限
    -    NAME/Makefile    = new
    RW    Name/            = new

/* 推荐用法 */
repo project
    // 有效防止误操作:
    //     指定admin对branch的读写权限,防止误操作将本地的临时性branch推送到服务器端
    //     如果确定需要新增一个branch,则在下面新增一行,例如新增dev分支
    RW+ master$     =   admin   // admin 有读,写,强制写master分支的权限
    RW+ dev$        =   admin   // admin 有读,写,强制写dev分支的权限

    RW  dev$             =  dev1 dev2     // 普通developer仅能读写dev分支,且不能强制写
    -   refs/tags/v[0-9] =  dev2 dev2     // 限制普通用户不能创建以v加上数字开头的release tag
    // 如果不同的用户(组)分别负责完全独立的两个子系统,则可通过类似以下这种方式排除互相干扰
    -   NAME/net/        =  dev1    // dev1 不能修改net子系统下的文件
    -   NAME/arch/       =  dev2    // dev2 不能修改arch子系统下的文件

配置gitweb

本节主要参考配置Gitolite+Gitweb+Nginx

// 安装gitweb 和用于代码高亮的highlight
$ sudo apt-get install -y gitweb highlight

// 修改文件权限,用于gitweb读取
$ chmod 0027 /home/git.gitolite.rc
$ sudo usermod -a -G git www-data   // www-data 是运行nginx服务的用户
$ sudo chmod g+r    /home/git/projects.list
$ sudo chmod -R g+rx /home/git/repositories

// 将要显示的repo写入projects.list文件
$ cat projects.list
    testing.git

// 修改/etc/gitweb.conf,修改以下几个关键值
$ cat /etc/gitweb.conf
    # path to git projects (<project>.git)
    $projectroot = "/home/git/repositories/";

    # directory to use for temp files
    $git_temp = "/tmp";

    # target of the home link on top of all pages
    #$home_link = $my_uri || "/";

    # html text to include at home page
    #$home_text = "indextext.html";

    # file with project list; by default, simply scan the projectroot dir.
    $projects_list = "/home/git/projects.list";
    $strict_export = 1;

    # stylesheet to use
    #@stylesheets = ("static/gitweb.css");

    # javascript code for gitweb
    $javascript = "static/gitweb.js";

    # logo to use
    $logo = "static/git-logo.png";

    # the 'favicon'
    #$favicon = "static/git-favicon.png";

    # git-diff-tree(1) options to use for generated patches
    #@diff_opts = ("-M");
    @diff_opts = ();

    $feature {'blame'}{'default'} = [1];
    $feature {'blame'}{'override'} = 1;

    $feature {'snapshot'}{'default'} = ['zip', 'tgz'];
    $feature {'snapshot'}{'override'} = 1;

    $feature{'highlight'}{'default'} = [1];

// 配置nginx
$ sudo apt-get install spawn-fcgi fcgiwrap
// 修改/etc/init/d/fcgi.fcgiwrap,将FCGI_USER FCGI_GROUP FCGI_SOCKET_OWNER FCGI_SOCKET_GROUP 都修改为运行web服务的用户
// 在nginx的配置文件中添加一个新的server段
    server {
        listen 80;
        server_name gitweb.example.com;
        access_log  /home/wwwlogs/access.log  main;

        location / {
            root /usr/share/gitweb;
            index index.cgi;
            include fastcgi_params;
            gzip off;
            fastcgi_param GITWEB_CONFIG /etc/gitweb.conf;

            if ($uri ~ "/index.cgi") {
                fastcgi_pass unix:/var/run/fcgiwrap.socket;
            }
        }
    }

// 重启fcgiwrap和nginx
$ sudo service fcgiwrap restart
$ sudo nginx -s reload

参考资料

Gitolite 构建 Git 服务器
配置Gitolite+Gitweb+Nginx
gitolite all-in-one page