1. 程式人生 > >使用Smart HTTP和Gitweb搭建簡易個人git伺服器

使用Smart HTTP和Gitweb搭建簡易個人git伺服器

剛接手了老師的一個安卓專案,考慮到實驗室閒置了一臺PC,決定把這個pc配置成git伺服器,用來進行版本控制。以為是分分鐘鐘的事兒呢,結果用了一整天才搞定。被網上殘缺不全的新舊教程整懵了,決定自己寫一個。

協議選擇

git可以使用五種網路協議進行通訊:

  1. Local:團隊成員用不同賬戶登入同一臺電腦,或者共享一個掛載的NFS
    語法:git clone /opt/git/project.git 或 git clone file:///opt/git/project.git
    前者根據是否在同一個檔案系統,選擇硬連結或拷貝。後者類似網路傳輸,效率稍低。
  2. SSH:最常用的方式,使用簡單,方便搭建,加密傳輸+訪問認證
    語法:git clone ssh://
    [email protected]
    /project.git
     或 git clone [email protected]:project.git
  3. Git Protocol:最快的方式,但是沒有認證功能
  4. HTTP:最相容的方式,該協議一般不會被防火牆阻隔,有認證沒加密
    語法:git clone http://server/project.git
  5. HTTPS:最安全的方式,加密+認證,但效率低(SSL的握手需要6步)
    語法:git clone https://server/project.git

因為學校封SSH的22埠,而且有一個同學在校外,排除了SSH協議。HTTPS協議太慢,我們的專案不需要加密資料,排除。GIT協議連認證都沒有,太過簡陋,排除。不同賬戶登入一臺pc機遠端辦公,喪失了git作為分散式版本控制系統的優勢,排除。

最終,我決定用HTTP協議。用HTTP協議也有兩種方式:

  1. dumb http
  2. smart http

區別是,dumb http模式中,如果get請求的檔案在packfile中,只能請求整個packfile,即使你需要的只有其中的一個檔案。另外一方面,smart http模式中,在http伺服器後面,又加了一層CGI,叫git-http-backend,它會像git或ssh協議那樣,當請求到來後,把需要的檔案,從各個packfile中抽取,然後組成一個自定義packfile後再傳給客戶端。

故選擇Smart HTTP。既然都用HTTP協議了,乾脆把gitweb也配出來,方便通過瀏覽器檢視git的版本庫。下面是配置過程。

配置過程

1、軟硬體環境

  • Pentium Dual-Core CPU,32 bits
  • ubuntu 12.04 LTS
  • apache 2.4.7
  • git 1.9.1

apache2、git、gitweb的安裝:

apt-get install git
apt-get install gitweb
apt-get install apache2

2、建立git庫

我選擇在/srv/目錄下建立一個bare repo,叫test.git,並把該目錄下所有檔案的所有者和組都改成www-data(apache2的預設所有者和預設組),以便apache2有許可權訪問它。

cd /srv
git init --bare test.git
chown -R www-data:www-data test.git

3、配置apache2

apache2的總配置檔案是/etc/apache2/apache2.conf,它會讀取/etc/apache2/sites-enabled/下的配置檔案。而該目錄下的檔案,一般是/etc/apache2/sites-available/下配置檔案的軟連結。

開啟/etc/apache2/apache2.conf,在最後新增如下內容。每條命令的解釋,見註釋。

# 預設apache2只對兩個目錄(/usr/share和/var/www)有訪問許可權,如下指令賦予apache2對/srv的訪問許可權。
<Directory /srv/>
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

# 如果沒有這句,在其他機器上執行git clone等命令會返回403錯誤,參照最後一條“參考”
<Location />
    Options +ExecCGI
    Require all granted
</Location>

# 設定git的工程目錄
SetEnv GIT_PROJECT_ROOT /srv/
# 預設情況下,含有git-daemon-export-ok檔案的目錄才可以被匯出(用作git庫目錄)。設定這個環境變數以便所有目錄都可以被匯出
SetEnv GIT_HTTP_EXPORT_ALL

# 虛擬主機,匹配80埠的任何ip地址的請求,訪問gitweb
<virtualhost *:80>
    # 順便在/etc/hosts裡新增上一句:127.0.0.1 git.example.com。這樣,在伺服器上可以通過該名字訪問這個頁面
    ServerName git.example.com
    DocumentRoot /usr/share/gitweb
    ErrorLog ${APACHE_LOG_DIR}/git_error.log
    CustomLog ${APACHE_LOG_DIR}/git_access.log combined
</virtualhost>

# gitweb目錄新增ExecCGI的功能
<Directory /usr/share/gitweb>
    Options FollowSymLinks ExecCGI
    AddHandler cgi-script .cgi
    DirectoryIndex gitweb.cgi
</Directory>

# 對git庫的各種請求,執行git-http-backend.cgi
ScriptAliasMatch \
    "(?x)^/(.*/(HEAD | \
    info/refs | \
    objects/(info/[^/]+ | \
     [0-9a-f]{2}/[0-9a-f]{38} | \
     pack/pack-[0-9a-f]{40}\.(pack|idx)) | \
    git-(upload|receive)-pack))$" \
    /usr/lib/git-core/git-http-backend/$1
# 其餘的請求,執行gitweb.cgi
ScriptAlias / /usr/share/gitweb/gitweb.cgi

# 設定git push等操作的認證方式為檔案認證,/var/www/git-auth後面會建立。
<LocationMatch "^/.*/git-receive-pack$">
    AuthType Basic
    AuthName "Git Access"
    Require valid-user
    AuthBasicProvider file
    AuthUserfile /var/www/git-auth
</LocationMatch>

4、push操作的認證

預設git-http-backend的upload-pack是被置為真的,即可以執行git clone/pull/fetch。但是,預設receive-pack是被置為false,即不能git push。為了支援帶認證的git push,需要兩步操作。

第一步,開啟/srv/test.git/config,新增如下內容:

[http]
    receivepack = true

如果不加上面這句,git clone下來的版本庫,git push時會提示403錯誤,即沒有授權。

第二步,生成一個包含使用者名稱和密碼的檔案,該檔案能被apache2讀取,作為檔案認證的依據。假設我要新增兩個使用者mashu和ouyang,密碼在提示下輸入,我要執行如下命令:

cd /var/www
htpasswd -c git-auth mashu
htpasswd git-auth ouyang 

有了這個檔案,新增到上面的apache2的配置檔案中即可。

5、gitweb的配置

修改/etc/gitweb.conf中的一句:

$projectroot = "/srv"

6、重啟apache2

service apache2 restart

7、客戶端檢查

在客戶端電腦上,找一個目錄,執行如下命令

git clone http://server-ip/test.git test-repo
cd test-repo
echo "aaa" > file
git add file && git commit -am "first commit"
git push

然後,在瀏覽器上輸入http://server-ip,檢視剛才的操作是否記錄到gitweb上了。

參考