搭建本身的 Git 服務器

根據 RhodeCode 在 2016 年作過的一項分析報告 Version Control Systems Popularity in 2016,在現在的 VCS(版本控制系統)領域,Git 幾乎已經一統江山,在選擇本身的 VCS 時,有 87% 的人會選擇使用 Git,排在第二名的 SVN 只佔 6%,不管是從 Google Trends,仍是在 Stack Overflow 上的提問,均可以看到 Git 的爆發式增加。另外,根據 Eclipse 的社區調查 (Eclipse Community Survey),在 2010 年先後,SVN 的使用率都遠超其餘幾款 VCS,從 2010 年開始,SVN 的使用率開始快速下滑,相應的,Git 的使用率快速上升,並在 2014 年超過了 SVN。php

vcs-popularity-eclipse-community.jpg

如今,Git 已經成爲了程序員的必備技能,愈來愈多的企業開始採用 Git。在開源的世界裏,Github 是程序員彙集的狂歡之地,但這並不適合企業的私有項目,雖然 Github 也支持建立私有項目,可是搭建一個本身的 Git 服務器在不少時候多是更好的選擇,這篇博客將介紹並學習幾種搭建 Git 服務器的方法。html

Git 支持四種不一樣的傳輸協議:本地協議(Local)、HTTP(S) 協議、SSH(Secure Shell)協議以及 Git 協議,這四種協議在不一樣的場合有不一樣的用途,而且各有利弊,能夠根據實際狀況來選擇。java

1、本地協議

本地協議是 Git 最基本的協議,當咱們想在本地作一些 Git 實驗時,這將很是有用。咱們首先創建兩個目錄:/git/repo~/working,前者做爲遠程版本庫,後者做爲本地工做目錄。nginx

aneasystone@little-stone:~$ sudo mkdir -p /git/repo
aneasystone@little-stone:~$ sudo git init --bare /git/repo/test.git
已初始化空的 Git 倉庫於 /git/repo/test.git/
複製代碼

咱們在 /git/repo 目錄經過 git init --bare 命令建立一個裸倉庫(bare repository,即一個不包含當前工做目錄的倉庫),只要這一步,咱們就能夠開始使用了。接着咱們在工做目錄 clone 這個版本庫:git

aneasystone@little-stone:~$ cd ~/working/
aneasystone@little-stone:~/working$ git clone /git/repo/test.git
正克隆到 'test'...
warning: 您彷佛克隆了一個空倉庫。
完成。
複製代碼

而後咱們可使用 pullpush 就像操做其餘的版本庫同樣。程序員

aneasystone@little-stone:~/working$ cd test/
aneasystone@little-stone:~/working/test$ touch 1
aneasystone@little-stone:~/working/test$ touch 2
aneasystone@little-stone:~/working/test$ git add .
aneasystone@little-stone:~/working/test$ git commit -m 'first commit'
[master (根提交) 4983f84] first commit
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 1
 create mode 100644 2
aneasystone@little-stone:~/working/test$ sudo git push
[sudo] aneasystone 的密碼: 
對象計數中: 3, 完成.
Delta compression using up to 8 threads.
壓縮對象中: 100% (2/2), 完成.
寫入對象中: 100% (3/3), 205 bytes | 205.00 KiB/s, 完成.
Total 3 (delta 0), reused 0 (delta 0)
To /git/repo/test.git
 * [new branch]      master -> master
複製代碼

本地協議不只在作 Git 實驗時頗有用,若是你的團隊有一個共享文件系統,能夠在這個共享文件系統上建立一個遠程版本庫,團隊成員把這個共享文件系統掛在本地,就能夠直接使用本地協議進行協做開發,徹底不須要搭建一臺專門的 Git 服務器。github

2、SSH 協議

本地協議雖然簡單,可是通常來講並不適用,由於你沒法控制用戶對共享文件系統的操做,用戶擁有 push 權限也就意味着用戶對遠程目錄擁有完整的 Shell 權限,他們有可能會無心甚至有意的修改或刪除 Git 內部文件,損壞 Git 倉庫。算法

更安全的作法是使用專門的 Git 服務器,若是你有一臺可使用 SSH 鏈接的服務器,搭建 Git 服務將會很是簡單。首先咱們要確保服務器上運行着 SSH 服務(sshd),大多數 Linux 服務器版本都默認包含了該服務,若是沒有,能夠先安裝 openssh-server。而後在服務器上建立 Git 遠程版本庫:shell

root@myserver:~# mkdir -p /git/repo
root@myserver:~# git init --bare /git/repo/test.git
已初始化空的 Git 倉庫於 /git/repo/test.git/
複製代碼

而後在本地 clone 這個版本庫:apache

aneasystone@little-stone:~/working$ git clone ssh://root@myserver/git/repo/test.git
正克隆到 'test'...
root@myserver's password: warning: 您彷佛克隆了一個空倉庫。 複製代碼

能夠看到和使用本地協議幾乎同樣,不一樣的地方在於,在 clone 的時候須要在 URL 前面加上 ssh://root@myserver,你也可使用 scp 式的寫法:

$ git clone root@myserver:/git/repo/test.git
複製代碼

另一點不一樣的地方是,每次 pullpush 的時候都須要輸入遠程服務器的 root 密碼。很顯然,讓每一個 Git 用戶都使用 root 來訪問服務器是一種很不安全的作法,有幾種方法能夠解決這個問題:

  • 最顯而易見的方法是爲每一個 Git 用戶建立一個獨立的帳號,並分別爲他們分配對倉庫的讀寫權限,這種方法行的通,可是對帳號的管理很是麻煩,在團隊人員不是不少的時候能夠嘗試,可是並不推薦;
  • 另外一種方法是配置 SSH 服務器使用某個已有的認證系統來管理用戶,好比 LDAP,這在不少企業中是很常見的,這樣能夠省去用 adduser 手工管理服務器帳號的麻煩;
  • 還有一種方法是隻建立一個帳號,好比叫作 git,他對倉庫具備讀寫權限,你們都使用這個帳號來訪問倉庫。這種方法的好處是用戶管理起來比較簡單,並且可使用後面介紹的 authorized_keys 文件對用戶的公鑰進行管理;

下面咱們嘗試下第三種方法。首先在服務器上建立一個名叫 git 的帳號:

root@myserver:~# adduser git
Adding user `git' ... Adding new group `git' (1000) ...
Adding new user `git' (1000) with group `git' ...
Creating home directory `/home/git' ... Copying files from `/etc/skel' ...
Enter new UNIX password: 
Retype new UNIX password: 
passwd: password updated successfully
Changing the user information for git
Enter the new value, or press ENTER for the default
	Full Name []: git
	Room Number []:   
	Work Phone []: 
	Home Phone []: 
	Other []: 
Is the information correct? [Y/n] Y
複製代碼

再設置一下 git 倉庫的權限(默認狀況下,git 倉庫的權限爲 rwxr-xr-x,只有建立者 root 有寫的權限,也就意味着使用 git 帳號只能 clone pull,不能 push):

# chmod a+w -R /git/repo/test.git
複製代碼

咱們這裏很是粗暴的使用 chmod a+w 將 git 倉庫設置爲對全部人可寫,這裏能夠想想,若是咱們但願設置某些用戶對倉庫具備只讀的權限,該怎麼作呢?

而後就能夠在本地愉快的進行 git 操做了:

$ git clone git@myserver:/git/repo/test.git
複製代碼

到這裏彷佛一切都很正常,可是幾回實操以後你就會發現,每次 git 操做都要輸入一次密碼,這也太麻煩了,能不能「免密提交代碼」呢?首先咱們要知道,只要能經過 SSH 登錄到服務器,咱們就能操做 git,因此若是 SSH 能支持免密登錄,咱們就能夠「免密提交代碼」。還好,SSH 支持公鑰認證,這種認證方式無需密碼登錄。在 Linux 操做系統中,每一個用戶均可以擁有本身的一個或多個密鑰對(公鑰和私鑰成對出現),這些密鑰通常狀況會保存在 ~/.ssh 目錄下,在開始以前,咱們先確認下本身是否已經生成過公鑰了,能夠看下這個目錄下是否有 id_dsa.pubid_rsa.pub 這樣的文件,若是沒有,咱們經過 ssh-keygen 來生成:

aneasystone@little-stone:~/.ssh$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/aneasystone/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/aneasystone/.ssh/id_rsa.
Your public key has been saved in /home/aneasystone/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:4Ulpufuhs/AgDMb0VXnqMUTw6bD/HrAOI2z9c1cod9I aneasystone@little-stone
The key's randomart image is: +---[RSA 2048]----+ | .oo. | | oo+. | | . o.Oo | | o . . B++ | | + . ..So o | | . + . ..+. + E | | * * + oo + | | . o Oo+.o. | | **+. | +----[SHA256]-----+ 複製代碼

這樣咱們在 ~/.ssh 目錄生成了兩個文件,id_rsa 是你的私鑰,id_rsa.pub 是你的公鑰。關於私鑰和公鑰的原理以及 RSA 加密算法等內容能夠參考我以前寫過的一篇介紹 HTTPS 和證書 的文章。

咱們假設你的 Git 服務器是由專門的服務器管理員負責維護和管理,當你生成你的公鑰以後,就能夠給服務器管理員發送一封申請 Git 服務的郵件,並附上你的公鑰。服務器管理員在收到你的申請以後,若是贊成了,就能夠進行下面的操做:

首先將公鑰文件拷貝到服務器上:

# scp id_rsa.pub root@myserver:/home/git
複製代碼

將公鑰文件的內容追加到 git 帳戶的 authorized_keys 文件中(要注意的是,若是是第一次操做,/home/git 目錄下是沒有 .ssh 目錄的,須要手工建立 .ssh 目錄和 authorized_keys 文件):

root@myserver:/home/git# cat id_rsa.pub >> /home/git/.ssh/authorized_keys
複製代碼

後續若是有其餘的用戶申請 Git 服務,均可以按照這個步驟操做。一旦完成這個操做,服務器管理員將會回覆你的郵件,通知你 Git 服務已經開通,這個時候你再進行 git 操做就能夠不用輸入密碼了。關於 SSH 的使用,更詳細的步驟能夠參考 Github 上的這篇指南:Connecting to GitHub with SSH

做爲服務器管理員,關於 SSH 還有一點須要考慮,那就是 SSH 的安全問題。在上面介紹本地協議時,咱們說這種方式沒法控制用戶對 Git 倉庫的操做,沒法防止用戶有意或無心的損壞 Git 倉庫,使用 SSH 協議同樣存在這樣的問題,用戶能經過 SSH 拉取和提交代碼,也就意味着用戶能夠經過 SSH 鏈接到服務器,對 Git 倉庫進行任何操做,這是一件很讓人擔憂的事情。

所以,咱們還須要對 git 帳號作一些限制。默認狀況下,咱們新建帳號的登錄 shell 是 /bin/bash,這個配置在 /etc/passwd 文件中:

git:x:1000:1000:git,,,:/home/git:/bin/bash
複製代碼

可使用 chsh 命令修改用戶的登錄 shell,讓他不能經過 SSH 訪問服務器,怎麼修改呢?咱們能夠看一下 /etc/shells 文件,這裏定義了全部可使用的登錄 shell,你能夠將 /bin/bash 改爲這裏的任何一個:

root@myserver:~# cat /etc/shells 
# /etc/shells: valid login shells
/bin/sh
/bin/dash
/bin/bash
/bin/rbash
複製代碼

很顯然,這些 shell 並非咱們想要的,有沒有一個 shell 只容許用戶進行 git 操做,而不容許其餘操做呢?還好,Git 的軟件包提供了一個名叫 git-shell 的登錄 shell,咱們能夠把他加進去,通常狀況下位於 /usr/bin/git-shell。咱們使用 chsh 修改 git 的登錄 shell:

root@myserver:~# chsh git
Changing the login shell for git
Enter the new value, or press ENTER for the default
	Login Shell [/bin/bash]: /usr/bin/git-shell
複製代碼

這樣當用戶 git 經過 SSH 鏈接服務器時,就會直接被拒絕了。

3、Git 協議

SSH 協議解決了用戶直接操做 Git 倉庫的權限問題,可是若是咱們但願對除倉庫維護者以外的全部人都開放 Git 倉庫的只讀權限,這在開源項目中和企業內部每每是很常見的,任何人均可以去查看倉庫的代碼,這時管理員須要給每個用戶配置 SSH 密鑰是很是麻煩的。雖然也可使用變通的方法來達到這個效果,可是很繁瑣,下面是具體的步驟:

  • 使用 g+w 設置 Git 倉庫的權限,讓倉庫建立者所在的用戶組具備寫權限,而不是全部人都有寫權限(這一步一般也能夠在 git init 的時候加上 --shared 參數);
  • 而後將 git 帳號加到倉庫建立者的用戶組;
  • 再建立一個 git_ro 帳戶,這個帳戶對倉庫只有只讀權限;
  • 最後爲 git_ro 帳戶建立一個密鑰對,把 git_ro 的私鑰公開出來供全部人使用。

能夠看到使用 SSH 協議最終都逃不過受權這一步,並且公開私鑰的作法也不是很優雅。實際上,Git 提供了另外一種方式來讓這個操做更簡單,那就是 Git 協議。使用 Git 協議必需要在服務器上運行 Git 守護進程,git 命令自帶了一個 daemon 參數:

root@myserver:~# git daemon --reuseaddr --base-path=/git/repo/ /git/repo/
複製代碼

上面的各個參數能夠 參考 git-daemon 的文檔。git-daemon 會監聽 9418 端口,若是你的服務器有防火牆,須要將該端口添加到白名單,若是你使用的是阿里雲服務器,須要像下面這樣添加一個安全組規則:

security-group.jpg

爲了讓全部的用戶均可以訪問咱們的倉庫,還須要在倉庫目錄下建立一個名爲 git-daemon-export-ok 的文件:

root@myserver:~# cd /git/repo/test.git/
root@myserver:/git/repo/test.git/# touch git-daemon-export-ok
複製代碼

至此,全部人均可以經過 Git 協議來克隆或拉取項目源碼了(注意上面指定了 base-path 參數爲 /git/repo/,因此 URL 能夠直接寫 git://myserver/test.git):

aneasystone@little-stone:~/working$ git clone git://myserver/test.git
複製代碼

通常狀況下,服務器管理員還會作一些其餘的配置,譬如在服務器重啓時讓 Git 守護進程自動啓動,這有不少種方式能夠實現,能夠參考《Pro Git》 Git 守護進程 這一節的內容。

4、HTTP(S) 協議

咱們通常經過 Git 協議進行無受權訪問,經過 SSH 協議進行受權訪問,若是你的項目是內部項目,只針對部分受權用戶,那使用 SSH 協議就足夠了,可是若是既須要受權訪問也須要無受權訪問,可能須要 SSH 協議和 Git 協議搭配使用,這在維護上成本很高。這時就到了咱們的壓軸戲 —— HTTP 協議出場的時候了,它同時支持上面兩種訪問方式。

經過 HTTP 協議訪問 Git 服務是目前使用最普遍的方式,它支持兩種模式:舊版本的 Dumb HTTP 和 新版本的 Smart HTTP,Dumb HTTP 通常不多使用,下面除非特殊說明,所說的 HTTP 協議都是 Smart HTTP。使用 HTTP 協議的好處是可使用各類 HTTP 認證機制,好比用戶名/密碼,這比配置 SSH 密鑰要簡單的多,對普通用戶來講也更能接受。若是擔憂數據傳輸安全,也能夠配置 HTTPS 協議,這和普通的 Web 服務是同樣的。

下面咱們就來嘗試搭建一個基於 HTTP 協議的 Git 服務器。《Pro Git》上提供了一個基於 Apache 的配置示例,若是你是使用 Apache 做爲 Web 服務器,能夠參考之,咱們這裏使用 Nginx 來做爲 Web 服務器,其原理本質上是同樣的,都是經過 Web 服務器接受 HTTP 請求,並將請求轉發到 Git 自帶的一個名爲 git-http-backend 的 CGI 腳本

首先咱們安裝所需的軟件:

# apt-get install -y git-core nginx fcgiwrap apache2-utils
複製代碼

其中,Nginx 做爲 Web 服務器,自己是不能執行外部 CGI 腳本的,須要經過 fcgiwrap 來中轉,就像使用 php-fpm 來執行 PHP 腳本同樣。apache2-utils 是 Apache 提供的一個 Web 服務器的工具集,包含了一些有用的小工具,譬以下面咱們會用到的 htpasswd 能夠生成 Basic 認證文件。

啓動 nginx 和 fcgiwrap,並訪問 http://myserver 測試 Web 服務器是否能正常訪問:

# service nginx start
# service fcgiwrap start
複製代碼

而後咱們打開並編輯 Nginx 的配置文件(/etc/nginx/sites-available/default):

location / {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend;
        fastcgi_param GIT_HTTP_EXPORT_ALL "";
        fastcgi_param GIT_PROJECT_ROOT /git/repo;
        fastcgi_param PATH_INFO $uri;
        fastcgi_param REMOTE_USER $remote_user;
        fastcgi_pass unix:/var/run/fcgiwrap.socket;
}
複製代碼

這裏經過 fastcgi_param 設置了一堆的 FastCGI 參數,以下:

  • SCRIPT_FILENAME:指定 CGI 腳本 git-http-backend 的位置,表示每次 HTTP 請求會被轉發到該 CGI 腳本;
  • GIT_HTTP_EXPORT_ALL:git-http-backend 默認只能訪問目錄下有 git-daemon-export-ok 文件的 Git 倉庫,和上面介紹的 Git 協議是同樣的,若是指定了 GIT_HTTP_EXPORT_ALL,表示容許訪問全部倉庫;
  • GIT_PROJECT_ROOT:Git 倉庫的根目錄;
  • REMOTE_USER:若是有認證,將認證的用戶信息傳到 CGI 腳本;

改完以後咱們重啓 Nginx,並經過 HTTP 協議 clone 倉庫:

aneasystone@little-stone:~/working$ git clone http://myserver/test.git
複製代碼

4.1 開啓身份認證

到這裏一切 OK,可是當咱們 push 代碼的時候,卻會報下面的 403 錯誤:

aneasystone@little-stone:~/working/test$ git push origin master
fatal: unable to access 'http://myserver/test.git/': The requested URL returned error: 403
複製代碼

爲了解決這個錯誤,咱們能夠在 git-http-backend 的官網文檔 上找到這樣的一段描述:

By default, only the upload-pack service is enabled, which serves git fetch-pack and git ls-remote clients, which are invoked from git fetch, git pull, and git clone. If the client is authenticated, the receive-pack service is enabled, which serves git send-pack clients, which is invoked from git push.

第一次讀這段話可能會有些不知所云,這是由於咱們對這裏提到的 upload-packfetch-packreceive-packsend-pack 這幾個概念尚未什麼認識。可是咱們大抵能夠猜出來,默認狀況下,只有認證的用戶才能夠 push 代碼,若是某個 Git 倉庫但願全部用戶都有權限 push 代碼,能夠爲相應的倉庫設置 http.receivepack

root@myserver:/# cd /git/repo/test.git/
root@myserver:/git/repo/test.git# git config http.receivepack true
複製代碼

固然最好的作法仍是對 push 操做開啓認證,官網文檔上有一個 lighttpd 的配置 咱們能夠借鑑:

$HTTP["querystring"] =~ "service=git-receive-pack" {
	include "git-auth.conf"
}
$HTTP["url"] =~ "^/git/.*/git-receive-pack$" {
	include "git-auth.conf"
}
複製代碼

這個配置看上去很是簡單,可是想要理解爲何這樣配置,就必須去了解下 Git 的內部原理。正如上面 git-http-backend 文檔上的那段描述,當 Git 客戶端執行 git fetch, git pull, and git clone 時,會調用 upload-pack 服務,當執行 git push 時,會調用 receive-pack 服務,爲了更清楚的說明這一點,咱們來看看 Nginx 的訪問日誌。

執行 git clone

[27/Nov/2018:22:18:00] "GET /test.git/info/refs?service=git-upload-pack HTTP/1.1" 200 363 "-" "git/1.9.1"
[27/Nov/2018:22:18:00] "POST /test.git/git-upload-pack HTTP/1.1" 200 306 "-" "git/1.9.1"
複製代碼

執行 git pull

[27/Nov/2018:22:20:25] "GET /test.git/info/refs?service=git-upload-pack HTTP/1.1" 200 363 "-" "git/1.9.1"
[27/Nov/2018:22:20:25] "POST /test.git/git-upload-pack HTTP/1.1" 200 551 "-" "git/1.9.1"
複製代碼

執行 git push

[27/Nov/2018:22:19:33] "GET /test.git/info/refs?service=git-receive-pack HTTP/1.1" 401 204 "-" "git/1.9.1"
admin [27/Nov/2018:22:19:33] "GET /test.git/info/refs?service=git-receive-pack HTTP/1.1" 200 193 "-" "git/1.9.1"
admin [27/Nov/2018:22:19:33] "POST /test.git/git-receive-pack HTTP/1.1" 200 63 "-" "git/1.9.1"
複製代碼

能夠看到執行 clone 和 pull 請求的接口是同樣的,先請求 /info/refs?service=git-upload-pack,而後再請求 /git-upload-pack;而 push 是先請求 /info/refs?service=git-receive-pack,而後再請求 /git-receive-pack,因此在上面的 lighttpd 的配置中咱們看到了兩條記錄,若是要對 push 作訪問控制,那麼對這兩個請求都要限制。關於 Git 傳輸的原理能夠參考 《Pro Git》的 Git 內部原理 - 傳輸協議 這一節。

咱們依葫蘆畫瓢,Nginx 配置文件以下:

location @auth {
        auth_basic "Git Server";
        auth_basic_user_file /etc/nginx/passwd;

        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend;
        fastcgi_param GIT_HTTP_EXPORT_ALL "";
        fastcgi_param GIT_PROJECT_ROOT /git/repo;
        fastcgi_param PATH_INFO $uri;
        fastcgi_param REMOTE_USER $remote_user;
        fastcgi_pass unix:/var/run/fcgiwrap.socket;
}

location / {
        error_page 418 = @auth;
        if ( $query_string = "service=git-receive-pack" ) {  return 418; }
        if ( $uri ~ "git-receive-pack$" ) { return 418; }

        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend;
        fastcgi_param GIT_HTTP_EXPORT_ALL "";
        fastcgi_param GIT_PROJECT_ROOT /git/repo;
        fastcgi_param PATH_INFO $uri;
        fastcgi_param REMOTE_USER $remote_user;
        fastcgi_pass unix:/var/run/fcgiwrap.socket;
}
複製代碼

其中相同的配置咱們也能夠用 include 指令放在一個共用的配置文件裏,這樣咱們就實現了在 push 的時候須要填寫用戶名和密碼了。咱們經過 Nginx 的 auth_basic_user_file 指令來作身份認證,用戶名和密碼保存在 /etc/nginx/passwd 文件中,這個文件可使用上面提到的 apache2-utils 包裏的 htpasswd 來生成:

root@myserver:/# htpasswd -cb /etc/nginx/passwd admin 123456
複製代碼

另外,在 push 的時候,有時候可能會遇到 unpack failed: unable to create temporary object directory 這樣的提示錯誤:

aneasystone@little-stone:~/working/test$ git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 193 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
error: unpack failed: unable to create temporary object directory
To http://myserver/test.git
 ! [remote rejected] master -> master (unpacker error)
error: failed to push some refs to 'http://myserver/test.git'
複製代碼

這通常狀況下都是因爲 Git 倉庫目錄的權限問題致使的,在這裏 Git 倉庫的根目錄 /git/repo 是 root 建立的,而運行 nginx 和 fcgiwrap 的用戶都是 www-data,咱們能夠把 Git 倉庫目錄設置成對全部人可讀可寫,也能夠像下面這樣將它的擁有者設置成 www-data 用戶:

root@myserver:/# chown -R www-data:www-data /git/repo
複製代碼

4.2 憑證管理

上面咱們站在管理員的角度解決了用戶身份認證的問題,可是站在用戶的角度,每次提交代碼都要輸入用戶名和密碼是一件很痛苦的事情。在上面介紹 SSH 協議時,咱們可使用 SSH 協議自帶的公鑰認證機制來省去輸入密碼的麻煩,那麼在 HTTP 協議中是否存在相似的方法呢?答案是確定的,那就是 Git 的憑證存儲工具:credential.helper

譬如像下面這樣,將用戶名和密碼信息保存在緩存中:

$ git config --global credential.helper cache
複製代碼

這種方式默認只保留 15 分鐘,若是要改變保留的時間,能夠經過 --timeout 參數設置,或者像下面這樣,將密碼保存在文件中:

$ git config --global credential.helper store
複製代碼

這種方式雖然能夠保證密碼不過時,可是要記住的是,這種方式密碼是以明文的方式保存在你的 home 目錄下的。能夠借鑑操做系統自帶的憑證管理工具來解決這個問題, 好比 OSX Keychain 或者 Git Credential Manager for Windows。更多的內容能夠參考《Pro Git》憑證存儲 這一節。

除此以外,還有一種更簡單粗暴的方式:

aneasystone@little-stone:~/working$ git clone http://admin:123456@myserver/test.git
複製代碼

5、綜合對比

這一節對 Git 的四大協議作一個綜合對比。

  • 本地協議
    • 優勢:架設簡單,不依賴外部服務,直接使用現有文件和網絡權限,經常使用於共享文件系統
    • 缺點:共享文件系統的配置和使用不方便,且沒法保護倉庫被意外損壞,傳輸性能較低
  • SSH 協議
    • 優勢:架設簡單,全部數據通過受權加密,數據傳輸很安全,傳輸性能很高
    • 缺點:不支持匿名訪問,配置 SSH 的密鑰對小白用戶有必定的門檻
  • Git 協議
    • 優勢:對開放的項目很適用,無需受權,傳輸性能最高
    • 缺點:缺少受權機制,架設較麻煩,企業通常不會默認開放 9418 端口須要另行添加
  • HTTP/S 協議
    • 優勢:同時支持受權訪問和無受權訪問,傳輸性能較高,配合 HTTPS 也能夠實現數據安全
    • 缺點:架設 HTTP 服務較麻煩,認證憑證很差管理

6、更高級的工具

上面介紹的是搭建 Git 服務器最基本的方法,若是你只是但願能找一個版本控制系統來替代現有的 SVN,這也許就足夠了。但若是你但願你的版本控制系統能擁有一個更友好的 UI 界面,能更好的管理你的用戶和權限,能支持更現代的 Pull Request 功能以及能和 CI/CD 系統更緊密的聯繫起來,你就須要一個更高級的工具,你能夠試試 GitWebGitoliteGitlabGogsGitea,固然,若是你願意,你也能夠把代碼放在那些流行的代碼託管平臺上,好比 GithubBitbucket 等等。

參考

  1. Version Control Systems Popularity in 2016
  2. Pro Git 第二版
  3. git-http-backend 的官網文檔
  4. Connecting to GitHub with SSH
  5. nginx fastcgi 配置
  6. Git遠程推送時記住用戶名和密碼
  7. 搭建Git服務器 - 廖雪峯的官方網站
  8. 在 Ubuntu 系統上配置 Nginx Git 服務器- 張志敏的技術專欄
  9. Git 服務器基於nginx配置http(s)協議 | Yvanの平行時空
相關文章
相關標籤/搜索