Learn Git

協議

Git 可以使用四種主要的協定來傳輸資料:本地傳輸,SSH 協定,Git 協定和 HTTP 協定。下面分別介紹一下哪些情形應該使用(或避免使用)這些協定。

值得注意的是,除了 HTTP 協定外,其他所有協定都要求在伺服器端安裝並運行 Git。

本地協定

最基本的就是本地協議(Local protocol),所謂的遠端倉庫在該協定中的表示,就是硬碟上的另一個目錄。這常見於團隊每一個成員都對一個共用的檔案系統(例如 NFS)擁有訪問權,或者比較少見的多人共用同一台電腦的情況。後面一種情況並不安全,因為所有代碼倉庫實例都儲存在同一台電腦裡,增加了災難性資料損失的可能性。

如果你使用一個共用的檔案系統,就可以在一個本地檔案系統中克隆倉庫,推送和獲取。克隆的時候只需要將遠端倉庫的路徑作為 URL 使用,比如下面這樣:

$ git clone /opt/git/project.git

或者這樣:

$ git clone file:///opt/git/project.git

如果在 URL 開頭明確使用 file:// ,那麼 Git 會以一種略微不同的方式運行。如果你只給出路徑,Git 會嘗試使用硬連結或直接複製它所需要的檔。如果使用了 file:// ,Git 會調用它平時通過網路來傳輸資料的工序,而這種方式的效率相對較低。使用 file:// 首碼的主要原因是當你需要一個不包含無關引用或物件的乾淨倉庫副本的時候 — 一般指從其他版本控制系統導入的,或類似情形(參見第 9 章的維護任務)。我們這裡僅僅使用普通路徑,這樣更快。

要添加一個本地倉庫作為現有 Git 項目的遠端倉庫,可以這樣做:

$ git remote add local_proj /opt/git/project.git

然後就可以像在網路上一樣向這個遠端倉庫推送和獲取資料了。

優點

基於檔倉庫的優點在於它的簡單,同時保留了現存檔的許可權和網路存取權限。如果你的團隊已經有一個全體共用的檔案系統,建立倉庫就十分容易了。你只需把一份裸倉庫的副本放在大家都能訪問的地方,然後像對其他共用目錄一樣設置讀寫許可權就可以了。我們將在下一節“在伺服器上部署 Git ”中討論如何匯出一個裸倉庫的副本。

這也是從別人工作目錄中獲取工作成果的快捷方法。假如你和你的同事在一個項目中合作,他們想讓你檢出一些東西的時候,運行類似 git pull /home/john/project 通常會比他們推送到伺服器,而你再從伺服器獲取簡單得多。

缺點

這種方法的缺點是,與基本的網路連接訪問相比,難以控制從不同位置來的存取權限。如果你想從家裡的筆記型電腦上推送,就要先掛載遠端硬碟,這和基於網路連接的訪問相比更加困難和緩慢。

另一個很重要的問題是該方法不一定就是最快的,尤其是對於共用掛載的檔案系統。本地倉庫只有在你對資料存取速度快的時候才快。在同一個伺服器上,如果二者同時允許 Git 訪問本地硬碟,通過 NFS 訪問倉庫通常會比 SSH 慢。

SSH 協議

Git 使用的傳輸協議中最常見的可能就是 SSH 了。這是因為大多數環境已經支持通過 SSH 對伺服器的訪問 — 即便還沒有,架設起來也很容易。SSH 也是唯一一個同時支持讀寫操作的網路通訊協定。另外兩個網路通訊協定(HTTP 和 Git)通常都是唯讀的,所以雖然二者對大多數人都可用,但執行寫操作時還是需要 SSH。SSH 同時也是一個驗證授權的網路通訊協定;而因為其普遍性,一般架設和使用都很容易。

通過 SSH 克隆一個 Git 倉庫,你可以像下面這樣給出 ssh:// 的 URL:

$ git clone ssh://user@server/project.git

或者不指明某個協定 — 這時 Git 會預設使用 SSH :

$ git clone user@server:project.git

如果不指明用戶,Git 會默認使用當前登錄的用戶名連接伺服器。

優點

使用 SSH 的好處有很多。首先,如果你想擁有對網路倉庫的寫許可權,基本上不可能不使用 SSH。其次,SSH 架設相對比較簡單 — SSH 守護進程很常見,很多網路系統管理員都有一些使用經驗,而且很多作業系統都自帶了它或者相關的管理工具。再次,通過 SSH 進行訪問是安全的 — 所有資料傳輸都是加密和授權的。最後,和 Git 及本地協議一樣,SSH 也很高效,會在傳輸之前盡可能壓縮資料。

缺點

SSH 的限制在於你不能通過它實現倉庫的匿名訪問。即使僅為讀取資料,人們也必須在能通過 SSH 訪問主機的前提下才能訪問倉庫,這使得 SSH 不利於開源的項目。如果你僅僅在公司網路裡使用,SSH 可能是你唯一需要使用的協定。如果想允許對項目的匿名唯讀訪問,那麼除了為自己推送而架設 SSH 協定之外,還需要支援其他協定以便他人訪問讀取。

Git 協議

接下來是 Git 協議。這是一個包含在 Git 套裝軟體中的特殊守護進程; 它會監聽一個提供類似於 SSH 服務的特定埠(9418),而無需任何授權。打算支援 Git 協定的倉庫,需要先創建 git-daemon-export-ok 檔 — 它是協定進程提供倉庫服務的必要條件 — 但除此之外該服務沒有什麼安全措施。要麼所有人都能克隆 Git 倉庫,要麼誰也不能。這也意味著該協議通常不能用來進行推送。你可以允許推送操作;然而由於沒有授權機制,一旦允許該操作,網路上任何一個知道專案 URL 的人將都有推送許可權。不用說,這是十分罕見的情況。

優點

Git 協定是現存最快的傳輸協議。如果你在提供一個有很大訪問量的公共專案,或者一個不需要對讀操作進行授權的龐大項目,架設一個 Git 守護進程來供應倉庫是個不錯的選擇。它使用與 SSH 協定相同的資料傳輸機制,但省去了加密和授權的開銷。

缺點

Git 協議消極的一面是缺少授權機制。用 Git 協議作為訪問專案的唯一方法通常是不可取的。一般的做法是,同時提供 SSH 介面,讓幾個開發者擁有推送(寫)許可權,其他人通過 git:// 擁有唯讀許可權。 Git 協定可能也是最難架設的協議。它要求有單獨的守護進程,需要定制 — 我們將在本章的 “Gitosis” 一節詳細介紹它的架設 — 需要設定 xinetd 或類似的程式,而這些工作就沒那麼輕鬆了。該協議還要求防火牆開放 9418 埠,而企業級防火牆一般不允許對這個非標準埠的訪問。大型企業級防火牆通常會封鎖這個少見的埠。

HTTP/S 協議

最後還有 HTTP 協議。HTTP 或 HTTPS 協議的優美之處在於架設的簡便性。基本上,只需要把 Git 的裸倉庫檔放在 HTTP 的根目錄下,配置一個特定的 post-update 掛鉤(hook)就可以搞定(Git 掛鉤的細節見第 7 章)。此後,每個能訪問 Git 倉庫所在伺服器上 web 服務的人都可以進行克隆操作。下面的操作可以允許通過 HTTP 對倉庫進行讀取:

$ cd /var/www/htdocs/
$ git clone --bare /path/to/git_project gitproject.git
$ cd gitproject.git
$ mv hooks/post-update.sample hooks/post-update
$ chmod a+x hooks/post-update

這樣就可以了。Git 附帶的 post-update 掛鉤會默認運行合適的命令(git update-server-info)來確保通過 HTTP 的獲取和克隆正常工作。這條命令在你用 SSH 向倉庫推送內容時運行;之後,其他人就可以用下面的命令來克隆倉庫:

$ git clone http://example.com/gitproject.git

在本例中,我們使用了 Apache 設定中常用的 /var/www/htdocs 路徑,不過你可以使用任何靜態 web 服務 — 把裸倉庫放在它的目錄裡就行。 Git 的資料是以最基本的靜態檔的形式提供的(關於如何提供檔的詳情見第 9 章)。

通過 HTTP 進行推送操作也是可能的,不過這種做法不太常見,並且牽扯到複雜的 WebDAV 設定。由於很少用到,本書將略過對該內容的討論。如果對 HTTP 推送協議感興趣,不妨打開這個位址看一下操作方法:http://www.kernel.org/pub/software/scm/git/docs/howto/setup-git-server-over-http.txt 。通過 HTTP 推送的好處之一是你可以使用任何 WebDAV 伺服器,不需要為 Git 設定特殊環境;所以如果主機提供商支援通過 WebDAV 更新網站內容,你也可以使用這項功能。

優點

使用 HTTP 協定的好處是易於架設。幾條必要的命令就可以讓全世界讀取到倉庫的內容。花費不過幾分鐘。HTTP 協議不會佔用過多伺服器資源。因為它一般只用到靜態的 HTTP 服務提供所有資料,普通的 Apache 伺服器平均每秒能支撐數千個檔的併發訪問 — 哪怕讓一個小型伺服器超載都很難。

你也可以通過 HTTPS 提供唯讀的倉庫,這意味著你可以加密傳輸內容;你甚至可以要求用戶端使用特定簽名的 SSL 證書。一般情況下,如果到了這一步,使用 SSH 公共金鑰可能是更簡單的方案;不過也存在一些特殊情況,這時通過 HTTPS 使用帶簽名的 SSL 證書或者其他基於 HTTP 的唯讀連接授權方式是更好的解決方案。

HTTP 還有個額外的好處:HTTP 是一個如此常見的協議,以至於企業級防火牆通常都允許其埠的通信。

缺點

HTTP 協議的消極面在於,相對來說用戶端效率更低。克隆或者下載倉庫內容可能會花費更多時間,而且 HTTP 傳輸的體積和網路開銷比其他任何一個協議都大。因為它沒有按需供應的能力 — 傳輸過程中沒有服務端的動態計算 — 因而 HTTP 協定經常會被稱為傻瓜(dumb)協議。更多 HTTP 協定和其他協定效率上的差異見第 9 章。