Gitolite 構建 Git 服務器【轉】

做者: 北京羣英匯信息技術有限公司
網址: http://www.ossxp.com/
版本: 0.1-1
日期: 2010-10-07 14:52:19

http://www.ossxp.com/doc/git/gitolite.htmlhtml

若是不是要和他人協同開發,Git 根本就不須要架設服務器。Git 在本地能夠直接使用本地版本庫的路徑完成 git 版本庫間的操做。程序員

可是若是須要和他人分享版本庫、協做開發,就須要可以經過特定的網絡協議操做 Git 庫。github

Git 支持的協議很豐富,架設服務器的選擇也不少,不一樣的方案有着各自的優缺點。web

  HTTP Git-daemon SSH Gitosis, Gitolite
服務架設難易度 簡單 中等 簡單 複雜
匿名讀取 支持 支持 否* 否*
身份認證 支持 支持 支持
版本庫寫操做 支持 支持 支持
企業級受權支持 支持
是否支持遠程建庫 支持

注:正則表達式

  • SSH 協議和基於 SSH 的 Gitolite 等能夠經過空口令賬號實現匿名訪問。

1   SSH 協議

SSH 協議用於爲 Git 提供遠程讀寫操做,是遠程寫操做的標準服務,在智能HTTP協議出現以前,甚至是寫操做的惟一標準服務。算法

對於擁有 SHELL 權限的 SSH 登陸賬號,能夠直接用下面的 git 命令訪問,例如:shell

$ git clone <username>@<server>:/path/to/repo.git

說明:數組

  • <username> 是服務器 <server> 上的用戶賬號。
  • /path/to/repo.git 是服務器中版本庫的絕對路徑。若用相對路徑則相對於 username 用戶的主目錄而言。
  • 若是採用口令認證,不能像 HTTPS 協議那樣能夠在 URL 中同時給出登陸名和口令,必須每次鏈接時輸入。
  • 若是採用公鑰認證,則無須輸入口令。

SSH 協議來實現 Git 服務,有以下方式:安全

  • 其一是用標準的 ssh 賬號訪問版本庫。即用戶賬號能夠直接登陸到服務器,得到 shell。

  • 另外的方式是,全部用戶都使用同一個專用的 SSH 賬號訪問版本庫。各個用戶經過公鑰認證的方式用此專用 SSH 賬號訪問版本庫。而用戶在鏈接時使用的不一樣的公鑰能夠用於區分不一樣的用戶身份。

    Gitosis 和 Gitolite 就是實現該方式的兩個服務器軟件。

標準SSH賬號和專用SSH賬號的區別在於:

  標準SSH Gitosis/Gitolite
賬號 每一個用戶一個賬號 全部用戶共用同一個賬號
認證方式 口令或公鑰認證 公鑰認證
用戶是否能直接登陸 shell
安全性
管理員是否須要 shell
版本庫路徑 相對路徑或絕對路徑 相對路徑
受權方式 操做系統中用戶組和目錄權限 經過配置文件受權
對分支進行寫受權 Gitolite
對路徑進行寫受權 Gitolite
架設難易度 簡單 複雜

實際上,標準SSH,也能夠用公鑰認證的方式實現全部用戶共用同一個賬號。不過這相似於把一個公共賬號的登陸口令同時告訴給多我的。

  • 在服務器端(server)建立一個公共賬號,例如 anonymous

  • 管理員收集須要訪問 git 服務的用戶公鑰。如: user1.pub, user2.pub

  • 使用 ssh-copy-id 命令遠程將各個 git 用戶的公鑰加入服務器(server)的公鑰認證列表中。

    $ ssh-copy-id -i user1.pub anonymous@server
    $ ssh-copy-id -i user2.pub anonymous@server
    

    若是直接在服務器上操做,則直接將文件追加到 authorized_keys 文件中。

    $ cat /path/to/user1.pub >> ~anonymous/.ssh/authorized_keys
    $ cat /path/to/user2.pub >> ~anonymous/.ssh/authorized_keys
    
  • 在服務器端的 anonymous 用戶主目錄下創建 git 庫,就能夠實現多個用戶利用同一個系統賬號(git) 訪問 Git 服務了。

這樣作除了免除了逐一設置賬號,以及用戶無需口令認證以外,標準SSH部署 Git 服務的缺點一個也很多,並且由於用戶之間沒法區分,更沒法進行鍼對用戶受權。

下面重點介紹一下 SSH 公鑰認證,由於它們是後面介紹的 Gitosis 和 Gitolite 服務器軟件的基礎。

1.1   SSH 公鑰認證

關於公鑰認證的原理,維基百科上的這個條目是一個很好的起點: http://en.wikipedia.org/wiki/Public-key_cryptography

若是你的主目錄下不存在 .ssh 目錄,說明你的 SSH 公鑰/私鑰對還沒有建立。能夠用這個命令建立:

$ ssh-keygen

該命令會在用戶主目錄下建立 .ssh 目錄,並在其中建立兩個文件:

  • id_rsa

    私鑰文件。是基於 RSA 算法建立。該私鑰文件要妥善保管,不要泄漏。

  • id_rsa.pub

    公鑰文件。和 id_rsa 文件是一對兒,該文件做爲公鑰文件,能夠公開。

建立了本身的公鑰/私鑰對後,就可使用下面的命令,實現無口令登陸遠程服務器,即用公鑰認證取代口令認證。

$ ssh-copy-id -i .ssh/id_rsa.pub user@server

說明:

  • 該命令會提示輸入用戶 user 在 server 上的SSH登陸口令。
  • 當此命令執行成功後,再以 user 用戶登陸 server 遠程主機時,沒必要輸入口令直接登陸。
  • 該命令實際上將 .ssh/id_rsa.pub 公鑰文件追加到遠程主機 server 的 user 主目錄下的 .ssh/authorized_keys 文件中。

檢查公鑰認證是否生效,運行SSH到遠程主機,正常的話應該直接登陸成功。若是要求輸入口令則代表公鑰認證配置存在問題。若是SSH服務存在問題,能夠經過查看服務器端的 /var/log/auth.log 進行診斷。

1.2   SSH 主機別名

在實際應用中,有時須要使用多套公鑰/私鑰對,例如:

  • 使用缺省的公鑰訪問 git 賬號,獲取 shell,進行管理員維護工做。
  • 使用單首創建的公鑰訪問 git 賬號,執行 git 命令。
  • 訪問 github(免費的Git服務託管商)採用其餘公鑰。

如何建立指定名稱的公鑰/私鑰對呢?仍是用 ssh-keygen 命令,以下:

$ ssh-keygen -f ~/.ssh/<filename>

注:

  • 將 <filename> 替換爲有意義的名稱。
  • 會在 ~/.ssh 目錄下建立指定的公鑰/私鑰對。 文件 <filename> 是私鑰,文件 <filename>.pub 是公鑰。

將新生成的公鑰添加到遠程主機的 .ssh/authorized_keys 文件中,創建新的公鑰認證。例如:

$ ssh-copy-id -i .ssh/<filename>.pub user@server

這樣,就有兩個公鑰用於登陸主機 server,那麼當執行下面的 ssh 登陸指令,用到的是那個公鑰呢?

$ ssh user@server

固然是缺省公鑰 ~/.ssh/id_rsa.pub 。那麼如何用新建的公鑰鏈接 server 呢?

SSH 的客戶端配置文件 ~/.ssh/config 能夠經過建立主機別名,在鏈接主機時,使用特定的公鑰。例如 ~/.ssh/config 文件中的下列配置:

host bj
  user git
  hostname bj.ossxp.com
  port 22
  identityfile ~/.ssh/jiangxin

當執行

$ ssh bj

或者執行

$ git clone bj:path/to/repo.git

含義爲:

  • 登陸的 SSH 主機爲 bj.ossxp.com
  • 登陸時使用的用戶名爲 git 。
  • 認證時使用的公鑰文件爲 ~/.ssh/jiangxin.pub

2   Gitolite 服務架設

Gitolite 是一款 Perl 語言開發的 Git 服務管理工具,經過公鑰對用戶進行認證,並可以經過配置文件對寫操做進行基於分支和路徑的的精細受權。Gitolite 採用的是 SSH 協議而且使用 SSH 公鑰認證,所以須要您對 SSH 很是熟悉,不管是管理員仍是普通用戶。所以在開始以前,請確認已經通讀過以前的「SSH 協議」一章。

Gitolite 的官方網址是: http://github.com/sitaramc/gitolite 。從提交日誌裏能夠看出做者是 Sitaram Chamarty,最先的提交開始於 2009年8月。做者是受到了 Gitosis 的啓發,開發了這款功能更爲強大和易於安裝的軟件。Gitolite 的命名,做者的原意是 Gitosis 和 lite 的組合,不過由於 Gitolite 的功能愈來愈強大,已經超越了 Gitosis,所以做者笑稱 Gitolite 能夠看做是 Github-lite —— 輕量級的 Github。

我是在2010年8月才發現 Gitolite 這個項目,並嘗試將公司基於 Gitosis 的管理系統遷移至 Gitolite。在遷移和使用過程當中,增長和改進了一些實現,如:通配符版本庫的建立過程,對建立者的受權,版本庫名稱映射等。本文關於 Gitolite 的介紹也是基於我改進的 Gitosis 的版本。

Gitolite 的實現機制歸納以下:

  • Gitolite 安裝在服務器( server ) 某個賬號之下,例如 git 賬號。

  • 管理員經過 git 命令檢出名爲 gitolite-admin 的版本庫。

    $ git clone git@server:gitolite-admin.git
    
  • 管理員將 git 用戶的公鑰保存在 gitolite-admin 庫的 keydir 目錄下,並編輯 conf/gitolite.conf 文件爲用戶受權。

  • 當管理員對 gitolite-admin 庫的修改提交併 PUSH 到服務器以後,服務器上 gitolite-admin 版本庫的鉤子腳本將執行相應的設置工做。

    • 新用戶公鑰自動追加到服務器端安裝賬號的 .ssh/authorized_keys 中,並設置該用戶的 shell 爲 gitolite 的一條命令 gl-auth-command

      command="/home/git/.gitolite/src/gl-auth-command jiangxin",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa <公鑰內容來自於 jiangxin.pub ...>
      
    • 更新服務器端的受權文件 ~/.gitolite/conf/gitolite.conf

    • 編譯受權文件 ~/.gitolite/conf/gitolite.conf-compiled.pm

  • 用戶能夠用 git 命令訪問受權的版本庫。

  • 當用戶以 git 用戶登陸 ssh 服務時,由於公鑰認證的相關設置,再也不直接進入 shell 環境,而是打印服務器端 git 庫受權信息後立刻退出。

    即用戶不會經過 git 用戶進入服務器的 shell,也就不會對系統的安全形成威脅。

  • 當管理員受權,用戶能夠遠程在服務器上建立新版本庫。

下面介紹 Gitolite 的部署和使用。在下面的示例中,約定:服務器的名稱爲 server ,Gitolite 的安裝賬號爲 git ,管理員的 ID 爲 admin

2.1   安裝 Gitolite

Gitolite 要求 git 的版本必須是 1.6.2 或以上的版本,而且服務器要提供 SSH 服務。下面是 Gitolite 的安裝過程。

2.1.1   服務器端建立專用賬號

安裝 Gitolite,首先要在服務器端建立專用賬號,全部用戶都經過此賬號訪問 Git 庫。通常爲方便易記,選擇 git 做爲專用賬號名稱。

$ sudo adduser --system --shell /bin/bash --group git

建立用戶 git,並設置用戶的 shell 爲可登陸的 shell,如 /bin/bash,同時添加同名的用戶組。

有的系統,只容許特定的用戶組(如 ssh 用戶組)的用戶才能夠經過 SSH 協議登陸,這就須要將新建的 git 用戶添加到 ssh 用戶組中。

$ sudo adduser git ssh

爲 git 用戶設置口令。當整個 git 服務配置完成,運行正常後,建議取消 git 的口令,只容許公鑰認證。

$ sudo passwd git

管理員在客戶端使用下面的命令,創建無口令登陸:

$ ssh-copy-id git@server

至此,咱們已經完成了安裝 git 服務的準備工做,能夠開始安裝 Gitolite 服務軟件了。

2.1.2   Gitolite 的安裝/升級

本節的名字稱爲安裝/升級,是由於 Gitolite 的安裝和升級能夠採用下列一樣的步驟。

Gitolite 安裝能夠在客戶端執行,而不須要在服務器端操做,很是方便。安裝 Gitolite 的前提是:

  • 已經在服務器端建立了專有賬號,如 git
  • 管理員可以以 git 用戶身份經過公鑰認證,無口令方式登陸方式登陸服務器。

安裝和升級均可以按照下面的步驟進行:

  • 使用 git 下載 Gitolite 的源代碼。

    $ git clone git://github.com/ossxp-com/gitolite.git
    
  • 進入 gitolite/src 目錄,執行安裝。

    $ cd gitolite/src
    $ ./gl-easy-install git server admin
    

    命令 gl-easy-install 的第一個參數 git 是服務器上建立的專用賬號ID,第二個參數 server 是服務器IP或者域名,第三個參數 admin 是管理員ID。

  • 首先顯示版本信息。

    ------------------------------------------------------------------------
    
    you are upgrading     (or installing first-time)     to v1.5.4-22-g4024621
    
    Note: getting '(unknown)' for the 'from' version should only happen once.
    Getting '(unknown)' for the 'to' version means you are probably installing
    from a tar file dump, not a real clone.  This is not an error but it's nice to
    have those version numbers in case you need support.  Try and install from a
    clone
    
  • 自動建立名爲 admin 的私鑰/公鑰對。

    gl-easy-install 命令行的最後一個參數即用於設定管理員ID,這裏設置爲 admin

    ------------------------------------------------------------------------
    
    the next command will create a new keypair for your gitolite access
    
    The pubkey will be /home/jiangxin/.ssh/admin.pub.  You will have to choose a
    passphrase or hit enter for none.  I recommend not having a passphrase for
    now, *especially* if you do not have a passphrase for the key which you are
    already using to get server access!
    
    Add one using 'ssh-keygen -p' after all the setup is done and you've
    successfully cloned and pushed the gitolite-admin repo.  After that, install
    'keychain' or something similar, and add the following command to your bashrc
    (since this is a non-default key)
    
        ssh-add $HOME/.ssh/admin
    
    This makes using passphrases very convenient.
    

    若是公鑰已經存在,會彈出警告。

    ------------------------------------------------------------------------
    
    Hmmm... pubkey /home/jiangxin/.ssh/admin.pub exists; should I just (re-)use it?
    
    IMPORTANT: once the install completes, *this* key can no longer be used to get
    a command line on the server -- it will be used by gitolite, for git access
    only.  If that is a problem, please ABORT now.
    
    doc/6-ssh-troubleshooting.mkd will explain what is happening here, if you need
    more info.
    
  • 自動修改客戶端的 .ssh/config 文件,增長別名主機。

    即當訪問主機 gitolite 時,會自動用名爲 admin.pub 的公鑰,以 git 用戶身份,鏈接服務器

    ------------------------------------------------------------------------
    
    creating settings for your gitolite access in /home/jiangxin/.ssh/config;
    these are the lines that will be appended to your ~/.ssh/config:
    
    host gitolite
         user git
         hostname server
         port 22
         identityfile ~/.ssh/admin
    
  • 上傳腳本文件到服務器,完成服務器端軟件的安裝。

    gl-dont-panic                                                                                                             100% 3106     3.0KB/s   00:00
    gl-conf-convert                                                                                                           100% 2325     2.3KB/s   00:00
    gl-setup-authkeys                                                                                                         100% 1572     1.5KB/s   00:00
    ...
    gitolite-hooked                                                                                                           100%    0     0.0KB/s   00:00
    update                                                                                                                    100% 4922     4.8KB/s   00:00
    
    
    ------------------------------------------------------------------------
    
    the gitolite rc file needs to be edited by hand.  The defaults are sensible,
    so if you wish, you can just exit the editor.
    
    Otherwise, make any changes you wish and save it.  Read the comments to
    understand what is what -- the rc file's documentation is inline.
    
    Please remember this file will actually be copied to the server, and that all
    the paths etc. represent paths on the server!
    
  • 自動打開編輯器(vi),編輯 .gitolite.rc 文件,編輯結束,上傳到服務器。

    如下爲缺省配置,通常無須改變:

    • $REPO_BASE="repositories";

      用於設置 Git 服務器的根目錄,缺省是 Git 用戶主目錄下的 repositories 目錄,可使用絕對路徑。全部 Git 庫都將部署在該目錄下。

    • $REPO_UMASK = 0007; # gets you 'rwxrwx---'

      版本庫建立使用的掩碼。即新創建版本庫的權限爲 'rwxrwx---'。

    • $GL_BIG_CONFIG = 0;

      若是受權文件很是複雜,更改此項配置爲1,以避免產生龐大的受權編譯文件。

    • $GL_WILDREPOS = 1;

      缺省支持通配符版本庫受權。

    該配置文件爲 perl 語法,注意保持文件格式和語法。退出 vi 編輯器,輸入 ":q" (不帶引號)。

  • 至此完成安裝。

2.1.3   關於 SSH 主機別名

在安裝過程當中,gitolite 建立了名爲 admin 的公鑰/私鑰對,以名爲 admin.pub 的公鑰鏈接服務器,由 gitolite 提供服務。可是若是直接鏈接服務器,使用的是缺省的公鑰,會直接進入 shell。

那麼如何可以根據須要選擇不一樣的公鑰來鏈接 git 服務器呢?

別忘了咱們在前面介紹過的 SSH 主機別名。實際上剛剛在安裝 gitolite 的時候,就已經自動爲咱們建立了一個主機別名。 打開 ~/.ssh/config 文件,能夠看到相似內容,若是對主機別名不滿意,能夠修改。

host gitolite
     user git
     hostname server
     port 22
     identityfile ~/.ssh/admin

即:

  • 像下面這樣輸入 SSH 命令,會直接進入 shell,由於使用的是缺省的公鑰。

    $ ssh git@server
    
  • 像下面這樣輸入 SSH 命令,則不會進入 shell。由於使用名爲 admin.pub 的公鑰,會顯示 git 受權信息並立刻退出。

    $ ssh gitolite
    

2.1.4   其餘的安裝方法

上面介紹的是在客戶端遠程安裝 Gitolite,是最經常使用和推薦的方法。固然還能夠直接在服務器上安裝。

  1. 首先也要在服務器端先建立一個專用的賬號,如: git 。
$ sudo adduser --system --shell /bin/bash --group git
  1. 將管理員公鑰複製到服務器上。

管理員在客戶端執行下面的命令:

$ scp ~/.ssh/id_rsa.pub server:/tmp/admin.pub
  1. 服務器端安裝 Gitolite。

推薦採用源碼方式安裝,由於若是以平臺自帶軟件包模式安裝 Gitolite,其中不包含咱們對 Gitolite 的改進。

  • 從源碼安裝。

    使用 git 下載 Gitolite 的源代碼。

    $ git clone git://github.com/ossxp-com/gitolite.git
    

    建立目錄。

    $ sudo mkdir -p /usr/local/share/gitolite/conf /usr/local/share/gitolite/hooks
    

    進入 gitolite/src 目錄,執行安裝。

    $ cd gitolite/src
    $ sudo ./gl-system-install /usr/local/bin /usr/local/share/gitolite/conf /usr/local/share/gitolite/hooks
    
  • 採用平臺自帶的軟件包安裝。

    例如在 Debian/Ubuntu 平臺,執行下面命令:

    $ sudo aptitude install gitolite
    

    Redhat 則使用 yum 命令安裝。

  1. 在服務器端以專用賬號執行安裝腳本。

例如服務器端的專用賬號爲 git。

$ sudo su - git
$ gl-setup /tmp/admin.pub
  1. 管理員在客戶端,克隆 gitolite-admin 庫
$ git clone git@server:gitolite-admin

升級 Gitolite:

  • 只須要執行上面的第3個步驟便可完成升級。
  • 若是修改或增長了新的了鉤子腳本,還須要從新執行第4個步驟。
  • Gitolite 升級有可能要求修改配置文件: ~/.gitolite.rc

2.2   管理 Gitolite

2.2.1   管理員克隆 gitolite-admin 管理庫

當 gitolite 安裝完成後,在服務器端自動建立了一個用於 gitolite 自身管理的 git 庫: gitolite-admin.git

克隆 gitolite-admin.git 庫。別忘了使用SSH主機別名:

$ git clone gitolite:gitolite-admin.git

$ git clone gitolite:gitolite-admin.git
Initialized empty Git repository in /data/tmp/gitolite-admin/.git/
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (6/6), done.

$ cd gitolite-admin/

$ ls -F
conf/  keydir/

$ ls conf
gitolite.conf

$ ls keydir/
admin.pub

咱們能夠看出 gitolite-admin 目錄下有兩個目錄 conf/keydir/

  • keydir/admin.pub 文件

    目錄 keydir 下初始時只有一個用戶公鑰,即 amdin 用戶的公鑰。

  • conf/gitolite.conf 文件

    該文件爲受權文件。初始內容爲:

    #gitolite conf
    # please see conf/example.conf for details on syntax and features
    
    repo gitolite-admin
        RW+                 = admin
    
    repo testing
        RW+                 = @all
    

    缺省受權文件中只設置了兩個版本庫的受權:

    • gitolite-admin

      即本版本庫(gitolite管理版本庫)只有 admin 用戶有讀寫和強制更新的權限。

    • testing

      缺省設置的測試版本庫,設置爲任何人均可以讀寫以及強制更新。

2.2.2   增長新用戶

增長新用戶,就是容許新用戶可以經過其公鑰訪問 Git 服務。只要將新用戶的公鑰添加到 gitolite-admin 版本庫的 keydir 目錄下,即完成新用戶的添加。

  • 管理員從用戶獲取公鑰,並將公鑰按照 username.pub 格式進行重命名。

    用戶能夠經過郵件或者其餘方式將公鑰傳遞給管理員,切記不要將私鑰誤傳給管理員。若是發生私鑰泄漏,立刻從新生成新的公鑰/私鑰對,並將新的公鑰傳遞給管理員,並申請將舊的公鑰做廢。

    用戶從不一樣的客戶端主機訪問有着不一樣的公鑰,若是但願使用同一個用戶名進行受權,能夠按照 username@host.pub 方式命名公鑰文件,和名爲 username@pub 的公鑰指向同一個用戶 username

    Gitolite 也支持郵件地址格式的公鑰,即形如 username@gmail.com.pub 的公鑰。Gitolite 可以很智能的區分是以郵件地址命名的公鑰仍是相同用戶在不一樣主機上的公鑰。若是是郵件地址命名的公鑰,將以整個郵件地址做爲用戶名。

  • 管理員進入 gitolite-admin 本地克隆版本庫中,複製新用戶公鑰到 keydir 目錄。

    $ cp /path/to/dev1.pub keydir/
    $ cp /path/to/dev2.pub keydir/
    $ cp /path/to/jiangxin.pub keydir/
    
  • 執行 git add 命令,將公鑰添加入版本庫。

    $ git add keydir
    $ git status
    # On branch master
    # Changes to be committed:
    #   (use "git reset HEAD <file>..." to unstage)
    #
    #       new file:   keydir/dev1.pub
    #       new file:   keydir/dev2.pub
    #       new file:   keydir/jiangxin.pub
    #
    
  • 執行 git commit,完成提交。

    $ git commit -m "add user: jiangxin, dev1, dev2"
    [master bd81884] add user: jiangxin, dev1, dev2
     3 files changed, 3 insertions(+), 0 deletions(-)
     create mode 100644 keydir/dev1.pub
     create mode 100644 keydir/dev2.pub
     create mode 100644 keydir/jiangxin.pub
    
  • 執行 git push,同步到服務器,才真正完成新用戶的添加。

    $ git push
    Counting objects: 8, done.
    Delta compression using up to 2 threads.
    Compressing objects: 100% (6/6), done.
    Writing objects: 100% (6/6), 1.38 KiB, done.
    Total 6 (delta 0), reused 0 (delta 0)
    remote: Already on 'master'
    remote:
    remote:                 ***** WARNING *****
    remote:         the following users (pubkey files in parens) do not appear in the config file:
    remote: dev1(dev1.pub),dev2(dev2.pub),jiangxin(jiangxin.pub)
    

若是咱們這時查看服務器端 ~git/.ssh/authorized_keys 文件,會發現新增的用戶公鑰也附加其中:

# gitolite start
command="/home/git/.gitolite/src/gl-auth-command admin",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty    <用戶admin的公鑰...>
command="/home/git/.gitolite/src/gl-auth-command dev1",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty     <用戶dev1的公鑰...>
command="/home/git/.gitolite/src/gl-auth-command dev2",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty     <用戶dev2的公鑰...>
command="/home/git/.gitolite/src/gl-auth-command jiangxin",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty <用戶jiangxin的公鑰...>
# gitolite end

在以前執行 git push 後的輸出中,以 remote 標識的輸出是服務器端執行 post-update 鉤子腳本的輸出。其中的警告是說新添加的三個用戶在受權文件中沒有被引用。接下來咱們便看看如何修改受權文件,以及如何爲用戶添加受權。

2.2.3   更改受權

新用戶添加完畢,可能須要從新進行受權。更改受權的方法也很是簡單,即修改 conf/gitolite.conf 配置文件,提交併 push。

  • 管理員進入 gitolite-admin 本地克隆版本庫中,編輯 conf/gitolite.conf

    $ vi conf/gitolite.conf
    
  • 受權指令比較複雜,咱們先經過創建新用戶組嘗試一下更改受權文件。

    考慮到以前咱們增長了三個用戶公鑰以後,服務器端發出了用戶還沒有在受權文件中出現的警告。咱們就在這個示例中解決這個問題。

    • 例如咱們在其中加入用戶組 @team1,將新添加的用戶 jiangxin, dev1, dev2 都歸屬到這個組中。

      咱們只須要在 conf/gitolite.conf 文件的文件頭加入以下指令。用戶之間用空格分隔。

      @team1 = dev1 dev2 jiangxin
      
    • 編輯完畢退出。咱們能夠用 git diff 命令查看改動:

      咱們還修改了版本庫 testing 的受權,將 @all 用戶組改成咱們新創建的 @team1 用戶組。

      $ git diff
      diff --git a/conf/gitolite.conf b/conf/gitolite.conf
      index 6c5fdf8..f983a84 100644
      --- a/conf/gitolite.conf
      +++ b/conf/gitolite.conf
      @@ -1,10 +1,12 @@
       #gitolite conf
       # please see conf/example.conf for details on syntax and features
      
      +@team1 = dev1 dev2 jiangxin
      +
       repo gitolite-admin
           RW+                 = admin
      
       repo testing
      -    RW+                 = @all
      +    RW+                 = @team1
      
  • 編輯結束,提交改動。

    $ git add conf/gitolite.conf
    $ git commit -q -m "new team @team1 auth for repo testing."
    
  • 執行 git push ,同步到服務器,才真正完成受權文件的編輯。

    咱們能夠注意到,PUSH 後的輸出中沒有了警告。

    $ git push
    Counting objects: 7, done.
    Delta compression using up to 2 threads.
    Compressing objects: 100% (3/3), done.
    Writing objects: 100% (4/4), 398 bytes, done.
    Total 4 (delta 1), reused 0 (delta 0)
    remote: Already on 'master'
    To gitadmin.bj:gitolite-admin.git
       bd81884..79b29e4  master -> master
    

2.3   Gitolite 受權詳解

2.3.1   受權文件的基本語法

下面咱們看一個不那麼簡單的受權文件:

1   @admin = jiangxin wangsheng
2
3   repo gitolite-admin
4       RW+                 = jiangxin
5
6   repo ossxp/.+
7       C                   = @admin
8       RW                  = @all
9
10  repo testing
11      RW+                         =   @admin
12      RW      master              =   junio
13      RW+     pu                  =   junio
14      RW      cogito$             =   pasky
15      RW      bw/                 =   linus
16      -                           =   somebody
17      RW      tmp/                =   @all
18      RW      refs/tags/v[0-9]    =   junio

在上面的示例中,咱們演示了不少受權指令。

  • 第1行,定義了用戶組 @admin,包含兩個用戶 jiangxin 和 wangsheng。

  • 第3-4行,定義了版本庫 gitolite-admin。並指定只有用戶 jiangxin 纔可以訪問,並擁有讀(R)寫(W)和強制更新(+)的權限。

  • 第6行,經過正則表達式定義了一組版本庫,即在 ossxp/ 目錄下的全部版本庫。

  • 第7行,用戶組 @admin 中的用戶,能夠在 ossxp/ 目錄下建立版本庫。

    建立版本庫的用戶,具備對版本庫操做的全部權限。

  • 第8行,全部用戶均可以讀寫 ossxp 目錄下的版本庫,但不能強制更新。

  • 第9行開始,定義的 testing 版本庫受權使用了引用受權語法。

  • 第11行,用戶組 @admin 對全部的分支和里程碑擁有讀寫、重置、添加和刪除的受權。

  • 第12行,用戶 junio 能夠讀寫 master 分支。(還包括名字以 master 開頭的其餘分支,若是有的話)。

  • 第13行,用戶 junio 能夠讀寫、強制更新、建立以及刪除 pu 開頭的分支。

  • 第14行,用戶 pasky 能夠讀寫 cogito 分支。 (僅此分支,精確匹配)。

2.3.2   定義用戶組和版本庫組

conf/gitolite.conf 受權文件中,能夠定義用戶組或者版本庫組。組名稱以 @ 字符開頭,能夠包含一個或多個成員。成員之間用空格分開。

  • 例如定義管理員組:

    @admin = jiangxin wangsheng
    
  • 組能夠嵌套:

    @staff = @admin @engineers tester1
    
  • 除了做爲用戶組外,一樣語法也適用於版本庫組。

    版本庫組和用戶組的定義沒有任何區別,只是在版本庫受權指令中處於不一樣的位置。即位於受權指令中的版本庫位置則表明版本庫組,位於受權指令中的用戶位置則表明用戶組。

2.3.3   版本庫ACL

一個版本庫能夠包含多條受權指令,這些受權指令組成了一個版本庫的權限控制列表(ACL)。

例如:

repo testing
    RW+                 = jiangxin @admin
    RW                  = @dev @test
    R                   = @all

每個版本庫受權都以一條 repo 指令開始。

  • 指令 repo 後面是版本庫列表,版本之間用空格分開,還能夠包括版本庫組。

    注意:版本庫名稱不要添加 .git 後綴。在版本庫建立過程當中會自動添加 .git 後綴。

    repo sandbox/test1 sandbox/test2 @test_repos
    
  • repo 指令後面的版本庫也能夠用正則表達式定義的 通配符版本庫

    正則表達式匹配時,會自動在 通配符版本庫 的先後加上前綴 ^ 和後綴 $ 。這一點和後面將介紹的正則引用(refex)大不同。

    repo ossxp/.+
    

    不過有時候使用了過於簡單的正則表達式如: "myrepo." ,有可能產生歧義,讓 Gitolite 誤認爲是普通版本庫名稱,在服務器端自動建立名爲 myrepo..git 的版本庫。解決歧義的一個辦法是:在正則表達式的前面插入 ^ 符號,或者在表達式後面添加 $ 符號,形如:"^myrepo.$"。

在 repo 指令以後,是縮進的一條或者多條受權指令。受權指令的語法:

<權限>  [零個或多個正則表達式匹配的引用] = <user> [<user> ...]
  • 每條指令必須指定一個權限。權限能夠用下面的任意一個權限關鍵字:

    C, R, RW, RW+, RWC, RW+C, RWD, RW+D, RWCD, RW+CD 。

  • 權限後面包含一個可選的 refex(正則引用)列表。

    正則表達式格式的引用,簡稱正則引用(refex),對 Git 版本庫的引用(分支,里程碑等)進行匹配。

    若是在受權指令中省略正則引用,意味着對所有的 Git 引用(分支,里程碑等)都有效。

    正則引用若是不以 refs/ 開頭,會自動添加 refs/heads/ 做爲前綴。

    正則引用若是不以 $ 結尾,意味着後面能夠匹配任意字符,至關於添加 .*$ 做爲後綴。

  • 權限後面也能夠包含一個以 NAME/ 開頭的路徑列表,進行基於路徑的受權。

  • 受權指令以等號(=)爲標記分爲先後兩段,等號後面的是用戶列表。

    用戶之間用空格分隔,而且可使用用戶組。

不一樣的受權關鍵字有不一樣的含義,有的受權關鍵字只用在 特定 的場合。

  • C

    C 表明建立。僅在 通配符版本庫 受權時可使用。用於指定誰能夠建立和通配符匹配的版本庫。

  • R, RW, 和 RW+

    R 爲只讀。RW 爲讀寫權限。RW+ 含義爲除了具備讀寫外,還能夠對 rewind 的提交強制 PUSH。

  • RWC, RW+C

    只有當受權指令中定義了正則引用(正則表達式定義的分支、里程碑等),纔可使用該受權指令。其中 C 的含義是容許建立和正則引用匹配的引用(分支或里程碑等)。

  • RWD, RW+D

    只有當受權指令中定義了正則引用(正則表達式定義的分支、里程碑等),纔可使用該受權指令。其中 D 的含義是容許刪除和正則引用匹配的引用(分支或里程碑等)。

  • RWCD, RW+CD

    只有當受權指令中定義了正則引用(正則表達式定義的分支、里程碑等),纔可使用該受權指令。其中 C 的含義是容許建立和正則引用匹配的引用(分支或里程碑等),D 的含義是容許刪除和正則引用匹配的引用(分支或里程碑等)。

2.3.4   Gitolite 受權機制

Gitolite 的受權實際分爲兩個階段,第一個階段稱爲前Git階段,即在 Git 命令執行前,由 SSH 連接觸發的 gl-auth-command 命令執行的受權檢查。包括:

  • 版本庫的讀。

    用戶必須擁有版本庫至少一個分支的下列權限之一: R, RW, 或 RW+ ,則整個版本庫包含全部分支對用戶都可讀。

    而版本庫分支實際上在這個階段獲取不到,即版本庫的讀取不能按照分支受權,只能是版本庫的總體受權。

  • 版本庫的寫。

    版本庫的寫受權,則要在兩個階段分別進行檢查。第一階段的檢查是看用戶是否擁有下列權限之一: RW, RW+ 或者 C 受權。

    第二個階段檢查分支以及是否擁有強制更新。具體見後面的描述。

  • 版本庫的建立。

    僅對正則表達式定義的通配符版本庫有效。即擁有 C 受權的用戶,能夠建立和對應正則表達式匹配的版本庫。同時該用戶也擁有對版本庫的讀寫權限。

對受權的第二個階段的檢查,其實是經過 update 鉤子腳本進行的。

  • 由於版本庫的讀操做不執行 update 鉤子,因此讀操做只在受權的第一個階段(前Git階段)進行檢查,受權的第二個階段對版本庫的讀受權無任何影響。
  • 鉤子腳本 update 針對 PUSH 操做的各個分支進行逐一檢查,所以第二個階段能夠進行鍼對分支寫操做的精細受權。
  • 在這個階段也能夠獲取到要更新的新的和老的 ref 的 SHA 摘要,所以也能夠進行是否有回滾(rewind)的發生,便是否容許強制更新,還能夠對分支的建立和刪除進行受權檢測。
  • 基於路徑的寫受權,也是在這個階段進行的。

2.4   版本庫受權案例

Gitolite 的受權很是強大也很是複雜,所以從版本庫受權的實際案例來學習很是行之有效。

2.4.1   對整個版本庫進行受權

受權文件以下:

1  @admin = jiangxin
2  @dev   = dev1 dev2 badboy jiangxin
3  @test  = test1 test2
4
5  repo testing
6      R = @test
7      - = badboy
8      RW = @dev test1
9      RW+ = @admin

說明:

  • 用戶 test1 對版本庫具備寫的權限。

    第6行定義了 test1 所屬的用戶組 @test 具備只讀權限。第8行定義了 test1 用戶具備讀寫權限。

    Gitolite 的實現是讀權限和寫權限分別進行判斷並彙總(並集),從而 test1 用戶具備讀寫權限。

  • 用戶 jiangxin 對版本庫具備寫的權限,並能強制PUSH。

    第9行受權指令中的加號(+)含義是容許強制 PUSH。

  • 禁用指令,讓用戶 badboy 對版本庫只具備讀操做的權限。

    第7行的指令以減號(-)開始,是一條禁用指令。禁用指令只在受權的第二階段起做用,即只對寫操做起做用,不會對 badboy 用戶的讀權限施加影響。

    在第8行的指令中, badboy 所在的 @dev 組擁有讀取權限。但禁用規則會對寫操做起做用,致使 badboy 只有讀操做權限,而沒有寫操做。

2.4.2   通配符版本庫的受權

受權文件以下:

1  @administrators = jiangxin admin
2  @dev   = dev1 dev2 badboy
3  @test  = test1 test2
4
5  repo sandbox/.+$
6      C = @administrators
7      R = @test
8      - = badboy
9      RW = @dev test1

這個受權文件中的版本庫名稱中使用了正則表達式,匹配在 sandbox 下的任意版本庫。

Tip

正則表達式末尾的 $ 有着特殊的含義,表明匹配字符串的結尾,明確告訴 Gitolite 這個版本庫是通配符版本庫。

由於加號 + 既能夠做爲普通字符出如今版本庫的命名中,又能夠做爲正則表達式中特殊含義的字符,若是 Gitolite 將受權文件中的通配符版本庫誤判爲普通版本庫,就會自動在服務器端建立該版本庫,這是可能管理員不但願發生的。

在版本庫結尾添加一個 $ 字符,就明確表示該版本庫爲正則表達式定義的通配符版本庫。

我修改了 Gitolite 的代碼,能正確判斷部分正則表達式,可是最好仍是對簡單的正則表達式添加 ^ 做爲前綴,或者添加 $ 做爲後綴,避免誤判。

正則表達式定義的通配符版本庫不會自動建立。須要管理員手動建立。

Gitolite 原來對通配符版本庫的實現是克隆即建立,可是這樣很容易由於錄入錯誤致使錯誤的版本庫意外被建立。羣英匯改進的 Gitolite 須要經過 PUSH 建立版本庫。

admin 用戶的身份建立版本庫 sandbox/repos1.git

$ git push git-admin-server:sandbox/repos1.git master

建立完畢後,咱們對各個用戶的權限進行測試,會發現:

  • 用戶 admin 對版本庫具備寫的權限。

    這並非由於第6行的受權指令爲 @administrators 授予了 C 的權限。而是由於該版本庫是由 admin 用戶建立的,建立者具備對版本庫徹底的讀寫權限。

    服務器端該版本庫目錄自動生成的 gl-creator 文件記錄了建立者 ID 爲 admin

  • 用戶 jiangxin 對版本庫沒有讀寫權限。

    雖然用戶 jiangxin 和用戶 admin 同樣均可以在 sandbox/ 下建立版本庫,可是因爲 sandbox/repos1.git 已經存在而且不是 jiangxin 用戶建立的,因此 jiangxin 用戶沒有任何權限,不能讀寫。

  • 和以前的例子相同的是:

    • 用戶 test1 對版本庫具備寫的權限。
    • 禁用指令,讓用戶 badboy 對版本庫只具備讀操做的權限。
  • 版本庫的建立者還可使用 setperms 命令爲版本庫添加受權。具體用法參見下面的示例。

2.4.3   用戶本身的版本庫空間

受權文件以下:

1  @administrators = jiangxin admin
2
3  repo users/CREATOR/.+$
4      C = @all
5      R = @administrators

說明:

  • 用戶能夠在本身的名字空間( /usrs/<userid>/ )下,本身建立版本庫。

    $ git push dev1@server:users/dev1/repos1.git master
    
  • 設置管理員組對任何用戶在 users/ 目錄下建立的版本庫都有隻讀權限。

  • 用戶可使用 setperms 爲本身的版本庫進行二次受權

    $ ssh dev1@server setperms users/dev1/repos1.git
    R = dev2
    RW = jiangxin
    ^D
    

    即在輸入 setperms 命令後,進入一個編輯界面,輸入 ^D(Ctrl+D)結束編輯。

    也可使用輸入重定向,先將受權寫入文件,再用 setperms 命令加載。

    $ cat > perms << EOF
    R = dev2
    RW = jiangxin
    EOF
    
    $ ssh dev1@server setperms < perms
    
  • 用戶可使用 getperms 查看對本身版本庫的受權

    $ ssh dev1@server getperms users/dev1/repos1.git
    R = dev2
    RW = jiangxin
    

2.4.4   對引用的受權:傳統模式

傳統的引用受權,指的是受權指令中不包含 RWC, RWD, RWCD, RW+C, RW+D, RW+CD 受權關鍵字,只採用 RW, RW+ 的傳統受權關鍵字。

在只使用傳統的受權關鍵字的狀況下,有以下注意事項:

  • rewind 必須擁有 + 的受權。
  • 建立引用必須擁有 W 的受權。
  • 刪除引用必須擁有 + 的受權。
  • 若是沒有在受權指令中提供引用相關的參數,至關於提供 refs/.* 做爲引用的參數,意味着對全部引用均有效。

受權文件:

1  @administrators = jiangxin admin
2  @dev   = dev1 dev2 badboy
3
4  repo test/repo1
5      RW+ = @administrators
6      RW master refs/heads/feature/ = @dev
7      R   = @test

說明:

  • 第5行,版本庫 test/repo1 ,管理員組用戶 jiangxinadmin 能夠任意建立和刪除引用,而且能夠強制 PUSH。

  • 第6行的規則看似只對 master 和 refs/heads/feature/* 的引用受權,實際上 @dev 能夠讀取全部名字空間的引用。這是由於讀取操做沒法得到 ref 相關內容。

    即用戶組 @dev 的用戶只能對 master 分支,以及以 feature/ 開頭的分支進行寫操做,但不能強制 PUSH 和刪除。至於其餘分支和里程碑,則只能讀不能寫。

  • 至於用戶組 @test 的用戶,由於使用了 R 受權指令,因此不涉及到分支的寫受權。

2.4.5   對引用的受權:擴展模式

擴展模式的引用受權,指的是該版本庫的受權指令出現了下列受權關鍵字中的一個或多個: RWC, RWD, RWCD, RW+C, RW+D, RW+CD

  • rewind 必須擁有 + 的受權。
  • 建立引用必須擁有 C 的受權。
  • 刪除引用必須擁有 D 的受權。

受權文件:

repo test/repo2
    RW+C = @administrators
    RW+  = @dev
    RW   = @test

repo test/repo3
    RW+CD = @administrators
    RW+C  = @dev
    RW    = @test

說明:

對於版本庫 test/repo2.git

  • 用戶組 @administrators 中的用戶,具備建立和刪除引用的權限,而且能強制 PUSH。
  • 用戶組 @dev 中的用戶,不能建立引用,但能夠刪除引用,以及能夠強制 PUSH。
  • 用戶組 @test 中的用戶,能夠 PUSH 到任何引用,可是不能建立引用,不能刪除引用,也不能強制 PUSH。

對於版本庫 test/repo3.git

  • 用戶組 @administrators 中的用戶,具備建立和刪除引用的權限,而且能強制 PUSH。
  • 用戶組 @dev 中的用戶,能夠建立引用,並可以強制 PUSH,但不能刪除引用,
  • 用戶組 @test 中的用戶,能夠 PUSH 到任何引用,可是不能建立引用,不能刪除引用,也不能強制 PUSH。

2.4.6   對引用的受權:禁用規則的使用

受權文件:

1  repo testing

       ...

12     RW      refs/tags/v[0-9]        =   jiangxin
13     -       refs/tags/v[0-9]        =   dev1 dev2 @others
14     RW      refs/tags/              =   jiangxin dev1 dev2 @others

說明:

  • 用戶 jiangxin 能夠寫任何里程碑,包括以 v 加上數字開頭的里程碑。
  • 用戶 dev1, dev2 和 @others 組,只能寫除了以 v 加上數字開頭以外的其餘里程碑。
  • 其中以 - 開頭的受權指令創建禁用規則。禁用規則只在受權的第二階段有效,所以不能對用戶的讀取進行限制!

2.4.7   用戶分支

和建立用戶空間(使用了 CREATOR 關鍵字)的版本庫相似,還能夠在一個版本庫內,容許管理本身名字空間( USER 關鍵字)下的分支。在正則引用的參數中出現的 USER 關鍵字會被替換爲用戶的 ID。

受權文件:

repo test/repo4
    RW+CD = @administrators
    RW+CD refs/personal/USER/  = @all
    RW+    master = @dev

說明:

  • 用戶組 @administrators 中的用戶,對全部引用具備建立和刪除引用的權限,而且能強制 PUSH。
  • 全部用戶均可以在 refs/personal/<userid>/ (本身的名字空間)下建立、刪除引用。可是不能修改其餘人的引用。
  • 用戶組 @dev 中的用戶,對 master 分支具備讀寫和強制更新的權限,可是不能刪除。

2.4.8   對路徑的寫受權

Gitolite 也實現了對路徑的寫操做的精細受權,而且很是巧妙的是:在實現上增長的代碼能夠忽略不計。這是由於 Gitolite 把對路徑看成是特殊格式的引用的受權。

在受權文件中,若是一個版本庫的受權指令中的正則引用字段出現了以 NAME/ 開頭的引用,則代表該受權指令是針對路徑進行的寫受權,而且該版本庫要進行基於路徑的寫受權判斷。

示例:

1  repo foo
2      RW                  =   @junior_devs @senior_devs
3
4      RW  NAME/           =   @senior_devs
5      -   NAME/Makefile   =   @junior_devs
6      RW  NAME/           =   @junior_devs

說明:

  • 第2行,初級程序員 @junior_devs 和高級程序員 @senior_devs 能夠對版本庫 foo 進行讀寫操做。
  • 第4行,設定高級程序員 @senior_devs 對全部文件( NAME/ )進行寫操做。
  • 第5行和第6行,設定初級程序員 @junior_devs 對除了根目錄的 Makefile 文件外的其餘文件 ,具備寫權限。

2.5   建立新版本庫

Gitolite 維護的版本庫位於安裝用戶主目錄下的 repositories 目錄中,即若是安裝用戶爲 git ,則版本庫都建立在 /home/git/repositories 目錄之下。能夠經過配置文件 .gitolite.rc 修改缺省的版本庫的根路徑。

$REPO_BASE="repositories";

有多種建立版本庫的方式。一種是在受權文件中用 repo 指令設置版本庫(未使用正則表達式的版本庫)的受權,當對 gitolite-admin 版本庫執行 git push 操做,自動在服務端建立新的版本庫。另一種方式是在受權文件中用正則表達式定義的版本庫,不會即時建立,而是被受權的用戶在遠程建立後PUSH到服務器 上完成建立。

注意,在受權文件中建立的版本庫名稱不要帶 .git 後綴,在建立版本庫過程當中會自動在版本庫後面追加 .git 後綴。

2.5.1   在配置文件中出現的版本庫,即時生成

咱們嘗試在受權文件 conf/gitolite.conf 中加入一段新的版本庫受權指令,而這個版本庫尚不存在。新添加到受權文件中的內容:

repo testing2
    RW+                 = @all

而後將受權文件的修改提交併 PUSH 到服務器,咱們會看到受權文件中添加新受權的版本庫 testing2 被自動建立。

$ git push
Counting objects: 7, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 375 bytes, done.
Total 4 (delta 1), reused 0 (delta 0)
remote: Already on 'master'
remote: creating testing2...
remote: Initialized empty Git repository in /home/git/repositories/testing2.git/
To gitadmin.bj:gitolite-admin.git
   278e54b..b6f05c1  master -> master

注意其中帶 remote 標識的輸出,咱們看到版本庫 testing2.git 被自動初始化了。

此外使用版本庫組的語法(即用 @ 建立的組,用做版本庫),也會被自動建立。例以下面的受權文件片斷設定了一個包含兩個版本庫的組 @testing ,當將新配置文件 PUSH 到服務器上的時候,會自動建立 testing3.gittesting4.git

@testing = testing3 testing4

repo @testing
    RW+                 = @all

還有一種版本庫語法,是用正則表達式定義的版本庫,這類版本庫由於所指的版本庫並不肯定,所以不會自動建立。

2.5.2   通配符版本庫,管理員經過push建立

通配符版本庫是用正則表達式語法定義的版本庫,所指的非某一個版本庫而是和名稱相符的一組版本庫。首先要想使用通配符版本庫,須要在服務器端安裝用戶(如 git )用戶的主目錄下的配置文件 .gitolite.rc 中,包含以下配置:

$GL_WILDREPOS = 1;

使用通配符版本庫,能夠對一組版本庫進行受權,很是有效。可是版本庫的建立則不像前面介紹的那樣,不會在受權文件 PUSH 到服務器時建立,而是擁有版本庫建立受權(C)的用戶手工進行建立。

對於用通配符設置的版本庫,用 C 指令指定可以建立此版本庫的管理員(擁有建立版本庫的受權)。例如:

repo ossxp/.+
    C                   = jiangxin
    RW                  = dev1 dev2

管理員 jinagxin 能夠建立路徑符合正則表達式 "ossxp/.+" 的版本庫,用戶 dev1 和 dev2 對版本庫具備讀寫(可是沒有強制更新)權限。

使用該方法建立版本庫後,建立者的 uid 將被記錄在版本庫目錄下的 gl-creator 文件中。該賬號具備對該版本庫最高的權限。該通配符版本庫的受權指令中若是出現 CREATOR 將被建立者的 uid 替換。

  • 本地建庫

    $ mkdir somerepo
    $ cd somerepo
    $ git init
    $ git commit --allow-empty
    
  • 使用 git remote 指令添加遠程的源

    $ git remote add origin jiangxin@server:ossxp/somerepo.git
    
  • 運行 git push 完成在服務器端版本庫的建立

    $ git push origin master
    

克隆即建立,仍是PUSH即建立?

Gitolite 的原始實現是通配符版本庫的管理員在對不存在的版本庫執行 clone 操做時,自動建立。可是我認爲這不是一個好的實踐,會常常由於 clone 的 URL 寫錯,致使在服務器端建立垃圾版本庫。所以我從新改造了 gitolite 通配符版本庫建立的實現,改成在對版本庫進行 PUSH 的時候進行建立,而 clone 一個不存在的版本庫,會報錯退出。

2.5.3   直接在服務器端建立

當版本庫的數量不少的時候,在服務器端直接經過 git 命令建立或者經過複製建立可能會更方便。可是要注意,在服務器端手工建立的版本庫和 Gitolite 建立的版本庫最大的不一樣在於鉤子腳本。若是不能爲手工建立的版本庫正確設定版本庫的鉤子,會致使失去一些 Gitolite 特有的功能。例如:失去分支受權的功能。

一個由 Gitolite 建立的版本庫,hooks 目錄下有三個鉤子腳本實際上連接到 gitolite 安裝目錄下的相應的腳本文件中:

gitolite-hooked -> /home/git/.gitolite/hooks/common/gitolite-hooked
post-receive.mirrorpush -> /home/git/.gitolite/hooks/common/post-receive.mirrorpush
update -> /home/git/.gitolite/hooks/common/update

那麼手工在服務器上建立的版本庫,有沒有自動更新鉤子腳本的方法呢?

有,就是從新執行一遍 gitolite 的安裝,會自動更新版本庫的鉤子腳本。安裝過程一路按回車便可。

$ cd gitolite/src
$ ./gl-easy-install git server admin

除了鉤子腳本要注意之外,還要確保服務器端版本庫目錄的權限和屬主。

2.6   對 Gitolite 的改進

筆者對 Gitolite 進行擴展和改進,涉及到的內容主要包括:

  • 通配符版本庫的建立方式和受權。

    原來的實現是克隆即建立(克隆者須要被授予 C 的權限)。同時還要經過另外的受權語句爲用戶設置 RW 權限,不然建立者沒有讀和寫權限。

    新的實現是經過 PUSH 建立版本庫(PUSH 者須要被授予 C 權限)。沒必要再爲建立者賦予 RW 等權限,建立者自動具備對版本庫最高的受權。

  • 避免通配符版本庫誤判。

    通配符版本庫誤判,會致使在服務器端建立錯誤的版本庫。新的設計還能夠在通配符版本庫的正則表達式前或後添加 ^$ 字符,而不會形成受權文件編輯錯誤。

  • 改變缺省配置。

    缺省安裝即支持通配符版本庫。

  • 版本庫重定向。

    Gitosis 的一個很重要的功能:版本庫名稱重定向,沒有在 Gitolite 中實現。咱們爲 Gitolite 增長了這個功能。

    在Git服務器架設的開始,版本庫的命名可能很是隨意,例如 redmine 的版本庫直接放在根下,例如: redmine-0.9.x.git, redmine-1.0.x.git, ... 當 redmine 項目愈來愈複雜,可能就須要將其放在子目錄下進行管理,例如放到 ossxp/redmine/ 目錄下。

    只須要在 Gitolite 的受權文件中添加下面一行 map 語句,就能夠實現版本庫名稱重定向。使用舊的地址的用戶沒必要從新檢出,能夠繼續使用。

    map (redmine.*) = ossxp/redmine/$1
    

2.7   Gitolite 功能拓展

2.7.1   版本庫鏡像

Git 版本庫控制系統每每並不須要設計特別的容災備份,由於每個Git用戶就是一個備份。可是下面的狀況,就頗有必要考慮容災了。

  • Git 版本庫的使用者不多(每一個庫可能只有一個用戶)。
  • 版本庫檢出只限制在辦公區而且服務器也在辦公區內(全部雞蛋在一個籃子裏)。
  • Git 版本庫採用集中式的應用模型,須要創建雙機熱備(以便在故障出現時,實現快速的服務器切換)。

Gitolite 提供了服務器間版本庫同步的設置。原理是:

  • 主服務器經過配置文件 ~/.gitolite.rc 中的變量 $ENV{GL_SLAVES} 設置鏡像服務器的地址。
  • 從服務器經過配置文件 ~/.gitolite.rc 中的變量 $GL_SLAVE_MODE 設置從服務器模式。
  • 從主服務器端運行腳本 gl-mirror-sync 能夠實現批量的版本庫鏡像。
  • 主服務器的每個版本庫都配置 post-receive 鉤子,一旦有提交,即時同步到鏡像版本庫。

在多個服務器之間設置 Git 庫鏡像的方法是:

  • 每一個服務器都要安裝 Gitolite 軟件,並且要啓用 post-receive 鉤子。

    缺省的鉤子在源代碼的 hooks/common 目錄下,名稱爲 post-receive.mirrorpush ,要將其更名爲 post-receive 。不然版本庫的 post-receive 腳本不能生效。

  • 主服務器配置到從服務器的公鑰認證,而且配置使用特殊的 SHELL: gl-mirror-shell

    這是由於主服務器在向從服務器同步版本庫的時候,若是從服務器版本庫沒有建立,直接經過 SSH 登陸到從服務器,執行建立命令。所以須要經過一個特殊的SHELL,可以同時支持 Gitolite 的受權訪問以及 SHELL 環境。這個特殊的 SHELL 就是 gl-mirror-shell 。並且這個 SHELL,經過特殊的環境變量繞過服務器的權限檢查,避免由於受權問題致使同步失敗。

    實際應用中,不光主服務器,每一個服務器都進行相似設置,目的是主從服務器可能相互切換。

    在 Gitolite 不一樣的安裝模式下, gl-mirror-shell 的安裝位置可能不一樣。下面的命令用於在服務器端設置其餘服務器訪問時使用這個特殊的 SHELL。

    假設在服務器 foo 上,安裝來自服務器 bar 和 baz 的公鑰認證。公鑰分別是 bar.pub 和 baz.pub。

    • 對於在客戶端安裝方式部署的 Gitolite:

      # 在服務器 foo 上執行:
      $ export GL_ADMINDIR=` cd $HOME;perl -e 'do ".gitolite.rc"; print $GL_ADMINDIR'`
      $ cat bar.pub baz.pub |
          sed -e 's,^,command="'$GL_ADMINDIR'/src/gl-mirror-shell" ,' >> ~/.ssh/authorized_keys
      
    • 對於在服務器端安裝方式部署的 Gitolite, gl-mirror-shell 直接就能夠在路徑中找到。

      # 在服務器 foo 上執行:
      $ cat bar.pub baz.pub |
          sed -e 's,^,command="'$(which gl-mirror-shell)'" ,' >> ~/.ssh/authorized_keys
      

    在 foo 服務器上設置完畢,能夠從服務器 bar 或者 baz 上遠程執行:

    • 執行命令後退出

      $ ssh git@foo pwd
      
    • 進入 shell

      $ ssh git@foo bash -i
      
  • 在從服務器上設置配置文件 ~/.gitolite.rc

    進行以下設置後,將不容許用戶直接 PUSH 到從服務器。可是主服務器仍然能夠 PUSH 到從服務器,是由於主服務器版本庫在 PUSH 到從服務器時,使用了特殊的環境變量,可以跳過從服務器版本庫的 update 腳本。

    $GL_SLAVE_MODE = 1
    
  • 在主服務器上設置配置文件 ~/.gitolite.rc

    須要配置到從服務器的 SSH 鏈接,能夠設置多個,用空格分隔。注意使用單引號,避免 @ 字符被 Perl 看成數組解析。

    $ENV{GL_SLAVES} = 'gitolite@bar gitolite@baz';
    
  • 在主服務器端執行 gl-mirror-sync 進行一次完整的數據同步。

    須要以 Gitolite 安裝用戶身份(如git)執行。例如在服務器 foo 上執行到從服務器 bar 的同步。

    $ gl-mirror-sync gitolite@bar
    
  • 以後,每當用戶向主版本庫同步,都會經過版本庫的 post-receive 鉤子即時同步到從版本庫。

  • 主從版本庫的切換。

    切換很是簡單,就是修改 ~/.gitolite.rc 配置文件,修改 $GL_SLAVE_MODE 設置:主服務器設置爲 0,從服務器設置爲1。

2.7.2   Gitweb 和 Gitdaemon 支持

Gitolite 和 git-daemon 的整合很簡單,就是在版本庫目錄中建立一個空文件 git-daemon-export-ok

Gitolite 和 Gitweb 的整合,則提供了兩個方面的內容。一個是能夠設置版本庫的描述信息,用於在 gitweb 的項目列表頁面顯示。另一個是自動生成項目的列表文件供 Gitweb 參卡,避免 Gitweb 使用效率低的目錄遞歸搜索查找 Git 版本庫列表。

能夠在受權文件中設定版本庫的描述信息,並在 gitolite-admin 管理庫更新時建立到版本庫的 description 文件中。

reponame = "one line of description"
reponame "owner name" = "one line of description"
  • 第1行,爲名爲 reponame 的版本庫設定描述。
  • 第1行,同時設定版本庫的屬主名稱,和一行版本庫描述。

對於通配符版本庫,使用這種方法則很不現實。Gitolite 提供了 SSH 子命令,供版本庫的建立者使用。

$ ssh git@server setdesc description...
$ ssh git@server getdesc
  • 第一條指令用於設置版本庫的描述信息。
  • 第二條指令顯示版本庫的描述信息。

至於生成 Gitweb 所用的項目列表文件,缺省建立在用戶主目錄下的 projects.list 文件中。對於全部啓用 Gitweb 的 [repo] 小節設定的版本庫,或者經過版本庫描述隱式聲明的版本庫加入到版本庫列表中。

2.7.3   其餘功能拓展和參考

Gitolite 源碼的 doc 目錄包含用 markdown 標記語言編寫的手冊,能夠直接在 Github 上查看。也可使用 markdown 的文檔編輯工具將 .mkd 文檔轉換爲 html 文檔。轉換工具不少,有:rdiscount, Bluefeather, Maruku, BlueCloth2 等等。

在這些參考文檔中,你能夠發現 Gitolite 包含的更多的小功能或者祕籍,包括:

  • 版本庫設置。

    在受權文件經過 git config 指令爲版本庫進行附加的設置。例如:

    repo gitolite
        config hooks.mailinglist = gitolite-commits@example.tld
        config hooks.emailprefix = "[gitolite] "
        config foo.bar = ""
        config foo.baz =
    
  • 多級管理員受權。

    能夠爲不一樣版本庫設定管理員,操做 gitolite-admin 庫的部分受權文件。參見: doc/5-delegation.mkd

  • 自定義鉤子腳本。

    由於 Gitolite 佔用了幾個鉤子腳本,若是須要對同名鉤子進行擴展,Gitolite 提供了級聯的鉤子腳本,將定製放在級聯的鉤子腳本里。

    例如:經過自定義 gitolite-admin 的 post-update.secondary 腳本,以實現無需登陸服務器,更改 .gitolite.rc 文件。參見: doc/shell-games.mkd

    關於鉤子腳本的建立和維護,參見: doc/hook-propagation.mkd

  • 管理員自定義命令。

    經過設置配置文件中的 $GL_ADC_PATH 變量,在遠程執行該目錄下的可執行腳本,如: rmrepo

    具體參考: doc/admin-defined-commands.mkd

  • 建立匿名 SSH 認證。

    容許匿名用戶訪問 Gitolite 提供的 git 服務。即創建一個和 gitolite 服務器端賬號同 id 和主目錄的用戶,並設置其的特定 shell,而且容許口令爲空。

    具體參考: doc/mob-branches.mkd

  • 能夠經過名爲 @all 的版本庫進行全局的受權。

    可是不能在 @all 版本庫中對 @all 用戶組進行受權。

  • 版本庫很是或者用戶很是之多(幾千個)的時候,須要使用 大配置文件 模式。

    由於 Gitolite 的受權文件要先編譯才能生效,而編譯文件的大小是和用戶以及版本庫數量的乘積成正比的。選擇大配置文件模式,則不對用戶組和版本庫組進行擴展。

    參見: doc/big-config.mkd

  • 受權文件支持包含語句,能夠將受權文件分紅多個獨立的單元。

  • 執行外部命令,如 rsync。

  • Subversion 版本庫支持。

    若是在同一個服務器上以 svn+ssh 方式運行 Subversion 服務器,可使用同一套公鑰,同時爲用戶提供 Git 和 Subversion 服務。

  • HTTP 口令文件維護。經過 htpasswd SSH 子命令實現。

相關文章
相關標籤/搜索