Pages

Monday, 21 January 2013

使用Gitosis搭建Git服务器

更详细的教程请见http://git-scm.com/book/zh/ch4-7.html

安装必备工具

apt-get install git gitweb gitosis
用自己的公钥来初始化Gitosis

1
2
3
root@everet:/var# sudo -H -u git gitosis-init < /tmp/authorized_keys
Initialized empty Git repository in /home/git/repositories/gitosis-admin.git/
Reinitialized existing Git repository in /home/git/repositories/gitosis-admin.git/
对该仓库中的post-update 脚本加上可执行权限
root@everet:/home/git/repositories/gitosis-admin.git/hooks # chmod 755 post-update

克隆 Gitosis 的控制仓库

$ git clone git@everet.org:gitosis-admin.git
这会得到一个名为 gitosis-admin 的工作目录,主要由两部分组成:





1
2
3
4
5
6
7
8
Cedric Porter@CedricPorter-PC /cygdrive/h/Coding/everet
$ cd gitosis-admin/

Cedric Porter@CedricPorter-PC /cygdrive/h/Coding/everet/gitosis-admin
$ find .
./gitosis.conf
./keydir
./keydir/cedricporter@ET.pub
如果我们要增加工程:clover,我们可以修改gitosis.conf





1
2
3
4
5
6
7
8
9
10
$ cat gitosis.conf
[gitosis]

[group gitosis-admin]
writable = gitosis-admin
members = cedricporter@ET

[group clover]
writable = clover
members = cedricporter@ET
修改完后,提交并推送到服务器。





1
2
3
4
5
$ git commit -am 'add project clover'
[master 3d0dd1b] add project clover
Committer: U-CedricPorter-PC\Cedric Porter <Cedric Porter@CedricPorter-PC.(none)>

$ git push

Windows客户端

如果我们使用cygwin的git,那么就不会存在任何任何中文乱码问题。
如果我们使用TortoiseGit,我们可以安装一个utf-8的git,下载地址 http://tmurakam.org/git/
然后再装TortoiseGit http://code.google.com/p/tortoisegit/downloads/list,那么它会自动得到git的路径,否则,我们自己去TortoiseGit的设置中设置Git的路径。

此时,除了我们在资源管理器无法直接看到用符号标记的修改的中文文件名的文件,我们只能在右键的”Check for modifications“查看正确的被修的文件,因为在资源管理器中的中文文件名的文件的标记的基本是错误的。
-------------------------------------------------

搭建Git服务器


远程仓库实际上和本地仓库没啥不同,纯粹为了7x24小时开机并交换大家的修改。
GitHub就是一个免费托管开源代码的远程仓库。但是对于某些视源代码如生命的商业公司来说,既不想公开源代码,又舍不得给GitHub交保护费,那就只能自己搭建一台Git服务器作为私有仓库使用。
搭建Git服务器需要准备一台运行Linux的机器,强烈推荐用Ubuntu或Debian,这样,通过几条简单的apt命令就可以完成安装。
假设你已经有sudo权限的用户账号,下面,正式开始安装。
第一步,安装git:
$ sudo apt-get install git
第二步,创建一个git用户,用来运行git服务:
$ sudo adduser git
第三步,创建证书登录:
收集所有需要登录的用户的公钥,就是他们自己的id_rsa.pub文件,把所有公钥导入到/home/git/.ssh/authorized_keys文件里,一行一个。
第四步,初始化Git仓库:
先选定一个目录作为Git仓库,假定是/srv/sample.git,在/srv目录下输入命令:
$ sudo git init --bare sample.git
Git就会创建一个裸仓库,裸仓库没有工作区,因为服务器上的Git仓库纯粹是为了共享,所以不让用户直接登录到服务器上去改工作区,并且服务器上的Git仓库通常都以.git结尾。然后,把owner改为git:
$ sudo chown -R git:git sample.git
第五步,禁用shell登录:
出于安全考虑,第二步创建的git用户不允许登录shell,这可以通过编辑/etc/passwd文件完成。找到类似下面的一行:
git:x:1001:1001:,,,:/home/git:/bin/bash
改为:
git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell
这样,git用户可以正常通过ssh使用git,但无法登录shell,因为我们为git用户指定的git-shell每次一登录就自动退出。
第六步,克隆远程仓库:
现在,可以通过git clone命令克隆远程仓库了,在各自的电脑上运行:
$ git clone git@server:/srv/sample.git
Cloning into 'sample'...
warning: You appear to have cloned an empty repository.
剩下的推送就简单了。

管理公钥

如果团队很小,把每个人的公钥收集起来放到服务器的/home/git/.ssh/authorized_keys文件里就是可行的。如果团队有几百号人,就没法这么玩了,这时,可以用Gitosis来管理公钥。
这里我们不介绍怎么玩Gitosis了,几百号人的团队基本都在500强了,相信找个高水平的Linux管理员问题不大。

管理权限

有很多不但视源代码如生命,而且视员工为窃贼的公司,会在版本控制系统里设置一套完善的权限控制,每个人是否有读写权限会精确到每个分支甚至每个目 录下。因为Git是为Linux源代码托管而开发的,所以Git也继承了开源社区的精神,不支持权限控制。不过,因为Git支持钩子(hook),所以, 可以在服务器端编写一系列脚本来控制提交等操作,达到权限控制的目的。Gitolite就是这个工具。
这里我们也不介绍Gitolite了,不要把有限的生命浪费到权限斗争中。

小结

搭建Git服务器非常简单,通常10分钟即可完成;
要方便管理公钥,用Gitosis
要像SVN那样变态地控制权限,用Gitolite
------------------

CentOS SERVER下搭建Git服务器Gitosis

我们很多人知道Git可能是从Github开始的。因为Github是如此流行,几乎所有写代码的人都知道它,以至于一提到Git就以为是Github,其实两者并没有多少关系,只是名字类似而已(这有点像Java和JavaScript)。

实际上,Git是一个分布式版本控制软件,原来是Linux内核开发者Linus Torvalds为了更好地管理Linux内核开发而创立的。虽然Git比SVN优秀很多,但它们最初被设计出来的想法是一致的,那就是版本控制。而Github却是一个网站,充当Git公共服务器的作用,只要拥有Github账号的人都可以把自己的项目托管在那里,如果你舍不得花些钱,你的项目是强制公开的。所以,Github就是一个通过Git协议为众多开发者提供代码托管的地方,同时它提供了很多特性,第一次使得大家可以这么公开地讨论起各自的项目。

上面之所以说这么多,是因为今天要讲的Gitosis有点类似Github的功能。什么意思呢?就是我们可以在自己的服务器上安装Gitosis,那么这台服务器就可以向Github一样对外提供代码托管服务了,这对于很多不愿意把自己的代码公诸于世的公司来说最好不过了。
这里以CentOS充当服务器为例给大家讲解一下Gitosis的安装和配置。
1.编译安装git
yum install git
2.安装gitosis
  1. $ yum install python python-setuptools
  2. $ git clone git://github.com/res0nat0r/gitosis.git
  3. $ cd gitosis
  4. $ python setup.py install
网址:https://github.com/res0nat0r/gitosis
3.在开发机器上生成公共密钥(用来初始化gitosis)
  1. $ ssh-keygen -t rsa #不需要密码,一路回车就行(在本地操作)
  2. $ scp ~/.ssh/id_rsa.pub root@xxx:/tmp/ # 上传你的ssh public key到服务器
4.初始化gitosis[服务器端]
  1. $ adduser git # 新增一个git用户(先添加用户组 groupadd git)
  2. $ su git # 切换倒git用户下
  3. $ gitosis-init < /tmp/id_rsa.pub # id_rsa.pub是刚刚传过来的,注意放在/tmp目录主要是因为此目录权限所有人都有定权限的
  4. $ rm /tmp/id_rsa.pub # id_rsa.pub已经无用,可删除.
5.获取并配置gitosis-admin [客户端]
  1. $  git clone git@xxx:gitosis-admin.git  # 切换到root用户并在本地执行,获取gitosis管理项目,将会产生一个gitosis-admin的目录,里面有配置文件gitosis.conf和一个 keydir 的目录,keydir目录主要存放git用户名
  2. $  vi gitosis-admin/gitosis.conf  # 编辑gitosis-admin配置文件
如果无法git clone的话,可以使用git clone git@xxx:/home/git/repositories/gitosis-admin.git
# 在gitosis.conf底部增加
  1. [group 组名]
  2. writable = 项目名
  3. members = 用户  # 这里的用户名字 要和 keydir下的文件名字相一致
# VI下按ZZ(大写)两次会执行自动保存并退出,完成后执行
  1. $ cd gitosis-admin
  2. $ git add .
  3. $ git commit -a -m “xxx xx” # 要记住的是,如果每次添加新文件必须执行git add .,或者git add filename,如果没有新加文件,只是进行修改的话就可以执行此句。
# 修改了文件以后一定要PUSH到服务器,否则不会生效。
  1. $ git push
如果在git push的时候,遇到错误“ddress 192.168.0.77 maps to bogon, but this does not map back to the address – POSSIBLE BREAK-IN ATTEMPT!”,解决为修改/etc/hosts文件,将ip地址与主机名对应关系写进去就可以了。
注意:这里我们并没有进行任何的修改的,现在只有一个管理git的项目。下面的为新添加项目的配置,大家经常用到的也就是下面的操作的。
新建项目
到此步就算完成gitosis的初始化了。接下来的是新建一个新项目到服务器的操作,如第5步中配置gitosis.conf文件添加的是
  1. [group project1] # 组名称
  2. writable = project1 # 项目名称
  3. members = xxx # 用户名xxx一定要与客户端使用的用户名完全一样,否则无权限操作
提交修改并更新到git server服务端
  1. $ git commit -a -m “添加新项目project1,新项目的目录是project1,该项目的成员是xxx“ # “”里的内容自定
  2. $ git push
将新创建的项目提交到git server 上进行登记。以便客户可以操作新项目.
# 在客户端创建项目目录(客户端,当前用户为 XXX )
现在回到开发者客户端,上面创建了一个新项目project1并提交到了git server 。我们这里就创建此项目的信息.注意 项目名称 project1要与gitosis.conf文件配置一致,
  1. $ mkdir /home/用户/project1
  2. $ cd /home/用户/project1
  3. $ git init
  4. $ git add . # 新增文件 留意后面有一个点
  5. $ git commit -a -m “初始化项目project1″
# 然后就到把这个项目放到git server服务器上去.
  1. $ git remote add origin git@xxx:project1.git # xxx为服务器地址
  2. $ git push origin master
# 也可以把上面的两步合成一步
  1. $ git push git@xxx:project1.git master
说明:如果在执行 git push origin master 的时候,提示以下错误:
error: src refspec master does not match any.
error: failed to push some refs to ‘git@192.168.0.77:pro2.git’
这是由于项目为空的原因,我们在项目目录里新创建一个文件。经过->add -> commit -> push 就可以解决了
  1. $ touch a.txt
  2. $ git add a.txt
  3. $ git commit -a -m ‘add a.txt’
  4. $ git push
如果在git clone的时候遇到“

error: cannot run ssh: No such file or directory – cygwin git

”错误,则表示本机没有安装ssh命令。安装方法请参考:http://blog.haohtml.com/archives/13313,
有时候我们要更换电脑来重新开发项目。这个时候,只需要将id_rsa私钥放在home目录里的.ssh目录里就可以了。
-----------------

CentOS上,部署 Git 服务器

GitHub 确实好用,不过非付费用户托管在上面的项目只能是 public 的,想要托管私有项目的话,每个月要花费 7 美元(数量没有限制),一年下来还算一笔比较多的支出,所以如果你有私有项目需要托管的话,完全可以考虑自己部署一个 Git 服务器来使用,而且如果在国内有自己的服务器的话,使用速度方面会比 GitHub 要好。

Init 远程仓库

Git 服务器简单来说就是一台托管很多 Git 远程仓库的服务器。这里先建立一个远程仓库。
  • 新建一个用户 git
    useradd \
        -r \
        -s /bin/sh \
        -c 'git version control' \
        -d /home/git \
        git
    mkdir -p /home/git
    chown git:git /home/git
    
  • 切换至 git 用户,并初始化一个裸仓库 overwatch.git
    sudo -iu git
    git init --bare overwatch.git
    
这样,一个简易远程仓库就建立好了。

Clone 远程仓库

Git 支持的数据传输协议有下面这些
  • 本地传输
  • SSH 协议(最常见)
  • Git 协议
  • HTTP/HTTPS 协议(速度最慢)
本地传输、SSH 协议与 Git 协议在传输数据时都会尽可能对数据压缩,所以相对于 HTTP/HTTPS 协议这三个协议在传输文件时会快好多。下面配置 Git 服务器,使得它支持 SSH 与 Git 协议(本地传输与 HTTP/HTTPS 协议这里暂不做讲解),并通过这两种协议 Clone 上面建立的远程仓库。

SSH 协议

  • 切换一台机器,生成当前用户的 SSH 密钥(已经存在请略过这步)
     ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
    
    请将 your_email@example.com 替换你自己的邮箱地址。
  • 将生成的公钥添加到 Git 服务器
    ssh-copy-id -i ~/.ssh/id_rsa.pub git@urhost.com
    
    ~/.ssh/id_rsa.pub 是上一步生成的公钥文件的路径。这里也可以手动将公钥内容追加到到 Git 服务器 /home/git/.ssh/authorized_keys 里(使用用户 git )。 这里生成并上传公钥到 Git 服务器,是为了每次 Pull(Clone)和 Push 的时候,免去输入用户 git 的登陆密码的麻烦。
  • 使用 SSH 协议 Clone 刚刚建立的仓库
    git clone shenyu@urhost.com:overwatch.git
    
    urhost.com 是绑定到 Git 服务器上的域名,可以替换成 IP 地址。仓库的地址还可以使用 ssh:// 前缀来显示表明使用的协议,所以下面这两种仓库地址的写法都是可以的
    • shenyu@urhost.com:overwatch.git
    • ssh://shenyu@urhost.com/overwatch.git

Git 协议

为了使 Git 服务器支持 Git 协议,需要在 Git 服务器上安装 git-daemon。git-daemon 是 Git 自带的一项功能,它能够让所有人都能拥有读取仓库的权限。
  • 安装 git-daemon
    yum install git-daemon -y
    
  • 修改 git-daemon 的 systemd 配置文件 /usr/lib/systemd/system/git@.service
    vim /usr/lib/systemd/system/git@.service
    
    内容如下
    [Unit]
    Description=Git Repositories Server Daemon
    Documentation=man:git-daemon(1)
    
    [Service]
    User=git
    ExecStart=-/usr/libexec/git-core/git-daemon --base-path=/home/git/repositories
    --syslog --inetd --verbose
    StandardInput=socket
    
    git-daemon 配置文件路径,可以通过 rpm -ql git-daemon 来查看,这个方法同样适用于其他通过 yum 来安装的程序。
  • 启动 git-daemon
    systemctl start git.socket
    
  • 如果启用了防火墙,则需要开放 9418 端口
    • 新建配置文件 /etc/firewalld/services/git-daemon.xml
      vim /etc/firewalld/services/git-daemon.xml
      
      内容如下
      
      
        git-daemon (git)
Git is the protocol used to git version control. If you plan to make your git reponsitory cone via git protocol, enable this option.. protocol="tcp" port="9418"/>

  • 添加 git-daemon 服务
    firewall-cmd --reload
    firewall-cmd --get-services | grep "git-daemon"
    firewall-cmd --permanent --add-service=git-daemon
    firewall-cmd --reload
    
  • 使用 Git 协议 Clone 刚刚建立的仓库
    git clone git://urhost.com/overwatch.git
    

  • 上面配置的支持 SSH 协议与 Git 协议的 Git 服务器可以满足基本的私有仓库的需求,但是如果要实际用到团队协作开发中去的话,这种方式的缺点就显而易见了。比如,每次新建一个远程仓库和添加开发成员都需要登陆 Git 服务器来操作,这样管理很多项目和开发成员的话就会很麻烦。相对于这种简易的 Git 服务器,Gitosis 与 Gitolite 更适合团队协作开发使用,下面使用 Gitosis 来配置 Git 服务器。

    Gitosis

    • 安装 Gitosis
      git clone git://github.com/res0nat0r/gitosis.git
      cd gitosis
      python setup.py install
      
    • 新建一个 git 用户(和上面的一样,做过的话,就不要再做了)
      useradd \
          -r \
          -s /bin/sh \
          -c 'git version control' \
          -d /home/git \
          git
      mkdir -p /home/git
      chown git:git /home/git
      
    • 将你本地电脑的公钥上传至 Git 服务器上,没有公钥的话生成一下
       ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
       scp .ssh/id_rsa.pub root@urhost.com/tmp/
      
      请将 your_email@example.com 替换你自己的邮箱地址。
    • 切换至 git 用户,初始化 Gitosis
      sudo -iu git
      gitosis-init < /tmp/id_rsa.pub
      exit
      
      /tmp/id_rsa.pub 是上一步上传到 Git 服务器上的本地电脑的公钥。
    • 在本地电脑上 Clone gitosis-admin 仓库
      git clone git@urhost.com:gitosis-admin.git
      
      这个仓库就是用来管理 Git 服务器上的仓库和用户的,所以,想要添加删除 Git 服务器上的用户和仓库,只要修改这个仓库的内容然后上传就行了,相当方便。
    • 添加一个仓库和用户
      • 将用户的公钥文件拷贝到 keydir 目录下
        cp id_rsa.pub gitosis-admin/keydir/shenyu@local.pub
        
        本质上来说,Gitosis 是用来方便管理用户公钥的。
      • 编辑 gitosis-admin配置文件 gitosis.conf
        vim /gitosis-admin/gitosis.conf
        
        内容如下
        [gitosis]
        gitweb = no
        daemon = no
        
        [group gitosis-admin]
        members = shenyu@urhost.com
        writable = gitosis-admin
        
        [group developer]
        members = shenyu@ztgame.com shenyu@urhost.com
        writable = overwatch
        
        [repo overwatch]
        owner = 沈煜 
        description = Hero never die.
        gitweb = yes
        daemon = yes
        
        • gitweb :指定仓库是否显示在 gitweb 页面上(后面会配置 gitweb),可以在 gitosis 后配置让所有仓库都显示在 gitweb 中,也可以在 repo 后配置显示某个仓库(先将全局显示关闭)。
        • daemon :指定仓库是否支持 git 协议的(需要启动了 git-daemon 服务,上面配置过了),用法和 gitweb 一样
        • group :定义一个包含若干成员的组
        • members:定义组成员(成员的名字与成员的公钥文件名一致,不包括后缀名 .pub),成员之间用空格分隔
        • writable:定义组可以读写的仓库,仓库之间用空格分隔
        • repo :定义一个仓库
        • owner :仓库拥有者的信息
        • description :仓库的描述
        更详细的配置示例说明,请参考 gitosis 仓库下 example.conf 文件。
      • 提交上传
        cd gitosis-admin
        git add -A
        git commit -m "Add repo overwatch and user shenyu@ztgame.com"
        git push origin master
        
    • Clone 仓库
      Gitosis 添加的新仓库不能直接 Clone,需要本地初始化一下并 Push 一下
      git init
      git remote add origin git@urhost.com:overwatch.git
      touch README.md
      git add -A
      git commit -m "Init."
      git push origin master:master
      
      然后其他用户就可以通过 SSH 协议或者 Git 协议(只读)来 Clone 仓库了。

    Gitweb

    GitWeb 是 Git 自带一个 CGI 脚本,它提供了一个浏览 Git 仓库信息的 Web 界面(简化版的 GitHub)
    • 安装 fcgi-devel,fcgiwrap 和 fcgiwrap
      yum install fcgi-devel spawn-fcgi
      cd /usr/local/src/
      git clone git://github.com/gnosek/fcgiwrap.git
      cd fcgiwrap
      autoreconf -i
      ./configure
      make
      make install
      
    • 配置 fcgiwrap 的 systemd 配置
      vim /usr/lib/systemd/system/fcgiwrap.service
      
      内容如下
      [Unit]
      Description=Simple server for running CGI applications over FastCGI
      After=syslog.target network.target
      
      [Service]
      Type=forking
      Restart=on-abort
      PIDFile=/var/run/fcgiwrap.pid
      ExecStart=/usr/bin/spawn-fcgi -s /var/run/fcgiwrap.sock -P /var/run/fcgiwrap.pid -u nginx -g nginx -- /usr/local/sbin/fcgiwrap
      ExecStop=/usr/bin/kill -15 $MAINPID
      
      [Install]
      WantedBy=multi-user.target
      
    • 启动 fcgiwrap ,并设置它开机自动启动
      systemctl enable nginx fcgiwrap
      systemctl start nginx fcgiwrap
      
    • 配置 Nginx
      • 添加配置文件 /etc/nginx/conf.d/git.shenyu.conf
        vim /etc/nginx/conf.d/git.urhost.com.conf
        
        内容如下
        server
        {
            listen      80;
            server_name git.urhost.com;
            index       gitweb.cgi;
            root        /var/www/git;
            location /gitweb.cgi {
                include       fastcgi_params;
                gzip          off;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_pass  unix:/var/run/fcgiwrap.sock;
            }
        }
        
        这里绑定了域名 git.urhost.com(请替换成你自己的) 和 80 端口。
      • 加载 Nginx 配置
        nginx -s reload
        
      • 在域名的提供商那边设置 A 记录解析到 Git 服务器的 IP 地址上。
      • 将用户 nginx 加入 git 组
        usermod -a -G git nginx
        systemctl restart fcgiwrap
        
        这步操作的目的,是为了让 Nginx 能有权限读取仓库的内容(Nginx 默认的启动用户是 nginx),而且一定要重启一下 fcgiwrap ,否则无法立刻生效
      • 配置 gitweb
        • 编辑配置文件 /etc/gitweb.conf
          vim /etc/gitweb.conf
          
          内容如下
          our $projects_list = "/home/git/gitosis/projects.list";
          our $projectroot = "/home/git/repositories";
          our @git_base_url_list = qw(git://urhost.com ssh://git@urhost.com);
          
          • $projects_list :指定仓库清单的文件,这个文件里列出的所有仓库都会显示在 gitweb 中(存在的话),配合 gitosis 使用的话,gitosis 会自动维护仓库清单文件 projects.list
          • $projectroot :指定仓库存放的根目录
          • @git_base_url_list :指定显示在 gitweb 仓库详情里的 URL 前缀
      • 访问 GitWeb
        使用浏览器打开上面 Nginx 配置的域名,这里使用的是 http://git.urhost.com

    htpasswd

    htpasswd 可以用来给网站做简单的加密访问功能,这里将它用在 GitWeb 上。
    • 生成密码文件
      htpasswd bc /var/www/git/.htpasswd shenyu 123456
      
      htpasswd 命令最后两个参数是账号和密码。
    • 配置 Nginx
      server
      {
          listen      80;
          server_name git.shenyu.me;
          index       gitweb.cgi;
          root        /usr/share/nginx/html/git.shenyu.me;
          location /gitweb.cgi {
              include       fastcgi_params;
              gzip          off;
              fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
              fastcgi_pass  unix:/var/run/fcgiwrap.sock;
              auth_basic "gitweb-auth";
              auth_basic_user_file /usr/share/nginx/html/git.shenyu.me/.htpasswd;
          }
      }
      
    • 热更 Nginx 配置
      nginx -s reload
      
    现在访问 http://git.urhost.com 就需要输入账号和密码了。

    参考链接

    -------------------------------------

    Install gitweb using Nginx fastcgi 

    gitweb 是cgi, Nginx 只支持FastCGI, 所以需要加个wrapper

    下面是网上搜回来的资料,放在这里备忘:

    Slicehost Forum - Nginx + SCM
    cactuswax.net gitweb helper scripts
    NginxSimpleCGI

    不过后来发现有个 gitserve 更简单,用python 做的http server, 包在gitweb.cgi的外面,用起来感觉和hg serve一样方便了 :)