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://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 章。
- 1. 起步
- 1.1 關于版本控制
- 1.2 Git 簡史
- 1.3 Git 基礎
- 1.4 安裝 Git
- 1.5 初次運行 Git 前的配置
- 1.6 獲取幫助
- 1.7 小結
- 2. Git基礎
- 2.1 取得項目的 Git 倉庫
- 2.2 記錄每次更新到倉庫
- 2.3 查看提交歷史
- 2.4 撤消操作
- 2.5 遠程倉庫的使用
- 2.6 打標簽
- 2.7 技巧和竅門
- 2.8 小結
- 3. Git分支
- 3.1 何謂分支
- 3.2 分支的新建與合并
- 3.3 分支的管理
- 3.4 利用分支進行開發的工作流程
- 3.5 遠程分支
- 3.6 分支的衍合
- 3.7 小結
- 4. 服務器上的Git
- 4.1 協議
- 4.2 在服務器上部署 Git
- 4.3 生成 SSH 公鑰
- 4.4 架設服務器
- 4.5 公共訪問
- 4.6 GitWeb
- 4.7 Gitosis
- 4.8 Gitolite
- 4.9 Git 守護進程
- 4.10 Git 托管服務
- 4.11 小結
- 5. 分布式Git
- 5.1 分布式工作流程
- 5.2 為項目作貢獻
- 5.3 項目的管理
- 5.4 小結
- 6. Git工具
- 6.1 修訂版本(Revision)選擇
- 6.2 交互式暫存
- 6.3 儲藏(Stashing)
- 6.4 重寫歷史
- 6.5 使用 Git 調試
- 6.6 子模塊
- 6.7 子樹合并
- 6.8 總結
- 7. 自定義Git
- 7.1 配置 Git
- 7.2 Git屬性
- 7.3 Git掛鉤
- 7.4 Git 強制策略實例
- 7.5 總結
- 8. Git與其他系統
- 8.1 Git 與 Subversion
- 8.2 遷移到 Git
- 8.3 總結
- 9. Git 內部原理
- 9.2 Git 對象
- 9.3 Git References
- 9.4 Packfiles
- 9.5 The Refspec
- 9.6 傳輸協議
- 9.7 維護及數據恢復
- 9.8 總結
- 9.1 底層命令 (Plumbing) 和高層命令 (Porcelain)