前言:翻譯自《Pro Git》。正在學習Git,于是打算翻譯這篇文檔。一方面鍛煉自己英文文檔閱讀能力,翻譯成中文也可以方面别人。正所謂贈人玫瑰,手有餘香。鑒于本人水準有限,當然是不可能達到信、達、雅的水準。不過在翻譯過程中,我會盡量保證遵循原文,有些不好直譯的部分我會根據了解意譯,對于有些實在不知道用中文怎麼去表述但是不影響所講述内容的英文,我可能會直接忽略掉。此外,對于沒有把握的專有名詞,我會給出翻譯的同時保留原文。
1. 簡介
此處省略若幹字……
2. 起步
這一章的内容主要關于如何開始使用Git。我們首先要講一些關于版本控制工具的背景,然後講解如何在你的系統上讓Git運作起來,最後講講使用之前需要做的一些設定。在本章的末尾,你會明白為什麼Git會流行起來,而你為什麼應該用它。
2.1 關于版本控制
什麼是版本控制,為什麼你需要關注它?版本控制是能記錄一個或者一組檔案随着時間推移所發生的變化并且友善日後回憶起某個特定版本的系統。舉例來說,在這本書中,你會使用軟體源代碼作為被版本管理控制的檔案,然而實際上,你可以對幾乎電腦上任何類型的檔案進行版本控制。
如果你是一個圖形或者web設計師,你希望能夠儲存一張圖檔或者一個布局的每個版本,那麼使用一個版本控制系統(Version Control System)則是很明智的選擇。版本控制系統允許你将檔案恢複到之前的狀态,恢複整個項目至之前的狀态,比較随着時間推移發生的變化,看看是誰最後修改了什麼東西導緻出問題的,誰在何時報告了一個缺陷等等。使用版本控制系統還意味着如果你把東西弄亂了或者弄丢了你可以輕松的恢複他們。而完成這一切隻需要很小的開銷。
2.1.1本地版本控制系統
許多人進行版本控制的方法就是将檔案拷貝到另外一個目錄(或者如果他夠聰明的話,拷貝到一個帶有時間戳的目錄),這種方法很常見,因為他實作簡單,但是這種方式也是非常容易出錯的。你很容易忘了目前正在那個目錄進而不小心寫入錯誤的檔案或者幹脆将不想拷貝的檔案拷貝進去了。
要對付這個問題,程式員們在很久以前就開發出了具有一個小型資料庫的本地版本控制系統來儲存檔案的所有變化來進行版本控制,見圖1-1。

一個叫做rcs的系統調用是這類VCS工具中非常受歡迎的一個。這個系統調用至今仍然分布在許多的計算機中。甚至在非常受歡迎的MacOS X作業系統中,隻要你裝了開發者工具,就包含了這個指令。這個工具的基本思路就是跟蹤一個版本與另一個版本之間更新檔集(patch set,也就是檔案之間的不同),并且在硬碟上以特殊的形式記錄下來;然後,它可以根據一個個不定重新看到每個版本檔案的内容。
2.1.2 集中式版本控制系統
接下來碰到的問題就是需要和别的系統上的開發人員協作。為了解決這個問題,人們開發出了集中式版本控制系統(Centralized Version Control Systems,CVCSs)。這些版本控制系統,例如CVS、SVN和Perforce有一台包含了所有具有版本号的檔案的伺服器,和若幹個從中央簽出(check out)檔案的用戶端。這種模式在很長一段時間成為了版本控制的标準,如圖1-2。
這種模式有許多優點,尤其是相比本地版本控制管理來說。例如,每個人一定程度上知道這個項目中别人在幹些什麼事情。管理者可以細粒度地控制每個人能幹什麼,而管理一個CVCS比和每個用戶端的本地資料庫打交道要簡單多了。
盡管如此,這種模式也有一些知名的缺點。最明顯的一個就是中央伺服器的故障。如果中央伺服器當機一小時,那麼這段時間誰也不能和别人協同工作,也沒辦法儲存他們正在處理的檔案的版本資訊。如果中央伺服器的硬碟發生損壞,而這時候并沒有儲存合适的備份,那麼你慘了,出了少數用戶端上可能儲存的幾個項目快照(Snapshots),其他所有的東西都丢了——這個項目所有的曆史都不複存在了。本地版本控制系統同樣有這個問題——任何時候你将整個項目的曆史保留在一個地方,那麼你就會有丢失所有東西的風險。
2.1.3 分布式版本控制系統
這正是分布式版本控制系統(Distributed Version Control Systems, DVCSs)涉足的領域。在一個DVCS系統中(例如Git、Mercurial、Bazaar和Darcs),用戶端不是僅僅簽出檔案的最近快照,而是儲存整個工廠的鏡像。是以,如果某個伺服器挂了,這些系統通過它協作,任何一個用戶端工廠都可以拷給伺服器用來恢複。任何一次簽出實際上是所有資料的一個備份,如圖1-3:
此外,這種系統可以很好的同時和多個遠端工廠打交道。是以,你可以在一個項目内同時和不同團體以不同的方式協作。這樣允許你設定不同類型的工作流程,而這在傳統的集中式版本控制系統中是不可能的。
2.2 Git簡史
同許多偉大的事物一樣,Git誕生于一個創造性的毀滅和巨大的争議中(原文:Git began with a bit of creative destruction and fiery controversy)。Linux核心是一個超大規模的開源軟體項目。對于Linux核心維護的大部分時間(1991-2002),軟體的修改變更都是通過不定和歸檔檔案傳遞的。2002年,Linux核心項目開始使用一個叫做BitKeeper的專有的分布式版本控制系統。
2005年,Linux核心開發社群與BitKeeper的研發公司之間鬧僵了,而這個工具的免費使用權被收回了。這提醒了Linux研發社群(尤其是Linux的創始人Linus Torvalds)利用在使用BitKeeper過程中的體會開發屬于自己的工具。這個新系統的一些目标如下:
- 快速
- 設計簡單
- 對于非線性開發(數以千計的并行分支)的強大支援
- 完全分布式
- 能夠高效處理像Linux核心這樣的超大項目(速度和資料量)
自從2005年誕生以來,Git逐漸演進變得易于使用同時還保持了這些最初的優點。對于大的項目來說,它快速高效,并且對于非線性開發來說有着超乎想象的分支系統(見第三章)。
2.3 Git基礎
那麼,什麼是Git呢?這是一個需要搞清楚的重要問題,因為如果你明白什麼是Git以及它的基本工作原理,那麼高效的使用Git才可能比較簡單。當你學習Git的時候,你最好吧腦子裡你知道的關于其他VCS系統,例如SVN、Perforce的所有東西都清除掉。這樣的話有助于避免在使用這個工具是産生困惑。Git存儲與看待資訊的方式與其他系統有很大的不同,盡管使用者界面是類似的。明白這些概念可以防止你在使用Git的時候出現困惑。
2.3.1 快照(Snapshots),不是差别(Differences)
Git和SVN以及其他的版本控制系統最大的一個差別是Git看待其資料的方式。概念上來說,其他的版本控制系統将資訊存儲為一本基于檔案變化的清單。這些系統将它們保管的資訊看作是一些列檔案以及每個檔案随着時間推移的變化。如圖1-4所示。
Git并不是這樣存儲與看待它的資料的。相反,Git更多的把它的資料看成于一個小型檔案系統的一組快照。每一次你送出或者在Git中儲存你的項目的狀态,它首先做一個目前你的所有檔案的快照,然後存儲對這個快照的引用。為了保證效率,如果檔案沒有發生變化,Git不會再次儲存檔案——而是僅僅連結到之前那個已經存儲過的檔案。如圖1-5所示。
這是Git和幾乎所有其他的VCS之間的一個重要的差別。這使得Git幾乎重新考慮了所有其他VSC系統的所有方面的設計。這使得Git相比于一個單純的VCS系統,更像是一個帶有一系列功能極其強大的工具建構于其上的小型檔案系統。我們将會在講到第三章Git分支的時候體會到以這種方式看待資料所帶來的好處。
2.3.2 幾乎所有的操作都在本地
大部分Git的操作都隻需要本地的檔案和資源來進行——一般來說不需要從網絡上其他計算機擷取任何資訊。如果你習慣于那些每個操作幾乎都有網絡延遲的集中式版本控制系統,那麼Git的這方面特點會讓你覺得它具有上帝的力量。由于項目完整的曆史都儲存在本地,是以幾乎所有的操作都會立刻完成。
例如,要浏覽整個項目的曆史,Git不需要去遠端伺服器擷取曆史然後展現給你——它隻需要從本地資料庫中直接讀取。這意味着你幾乎即刻就能看到項目曆史。如果你想看一個檔案目前的版本和一個月前版本的變化,Git可以查找一個月前的這個檔案并且做一個本地的差别計算,而不需要讓遠端伺服器做或者pull到本地然後做本地差别計算。
這意味着如果你斷網或者沒連接配接×××也幾乎沒有什麼你不能做的。如果你在飛機或者火車上并且想做點工作,你可以開心的送出修改然後等到有網的時候再上傳。如果你在家,然後×××用戶端不能連接配接,你依然可以工作。而在其他的版本控制系統,這種情況要麼不可能發生,要麼很費勁。例如,在Perforce中,如果沒連接配接到伺服器,你做不了什麼東西;在CVS和SVN中,你可以編輯檔案,但是不能送出到資料庫中(除非資料庫是離線的)。這一點乍一看似乎沒什麼大不了,但是慢慢的你會被這個變化能帶來的好處shock到的。
2.3.3 Git具有完整性
Git中的所有東西在儲存前都會進行校驗和計算然後接下來通過這個checksum來進行引用。這意味着不可能在Git不知道的情況下修改Git管理的任何一個檔案或者目錄。這個功能在底層内置于Git中并且行程其設計哲學的一部分。如果檔案在傳輸中資料丢失或者檔案損壞了,Git立馬能檢測到。
Git使用SHA-1雜湊演算法來計算校驗和。這是一個40位的十六進制字元串,然後根據Git中的檔案内容或者目錄結構進行計算。一個SHA-1哈希看起來像這樣:24b9da6552252987aa493b52f8696cd6d3b00373。
在Git中到處都是用了這種哈希值,以至于你到處都可以看到他們。事實上,Git存儲檔案不是靠檔案名,在其資料庫中可尋址的存儲其内容的hash值。
2.3.4 Git隻添加資料
當你在Git中做操作,幾乎所有的操作都隻會向資料庫中添加資料。是以所有的操作幾乎都是可以撤銷或者擦除的。類似任何一個VCS,你可以丢失或者弄亂那些還沒有送出的變化,但是一旦你送出一個快照到Git,就不會丢失,尤其是當你定期将你的資料庫push到另一個倉庫中去。
這使得使用Git成為一種享受,因為我們知道,我們可以随便實驗,不用擔心把東西徹底弄糟。更加深入的了解Git如何存儲資料以及如何恢複看起來已經丢失的資料,詳見第九章内容。
2.3.5 三種狀态
注意啦。關于一點你需要特别注意,Git中的檔案有三種主要的狀态:已送出(committed)、已修改(modified)、暫存狀态(staged)。送出狀态意味着資料已經安全的送出到資料庫中。修改狀态意味着你有修改檔案,但是還沒有安全的送出到資料庫中。暫存狀态意味着你已經将一個已修改狀态的檔案放入下一個要送出的快照中。
Git中的項目有三個主要部分:Git目錄、工作目錄和暫存區域。
Git目錄是Git為你的項目存放中繼資料和對象資料庫的地方。這是Git中最重要的部分,當你從别的電腦拷貝一個倉庫時拷貝的就是這部分東西。
工作目錄是項目某個版本的一個checkout。這些檔案是從Git目錄中的壓縮了的資料庫中pull out出來然後存放在你的硬碟供你使用和修改的。
暫存區域是一個檔案,它存放在Git目錄中用以記錄下一次需要送出的檔案。暫存區域又有時被叫做是索引,但是現在它的标準叫法是暫存區域。
基本的Git工作流程如下:
1. 你在工作空間中修改檔案
2. 暫存檔案,将它們的快照放進暫存區
3. 送出——将暫存區檔案的快照永久存儲進Git目錄。
如果某個檔案的特定版本已經在Git中,那麼它被視為已經送出。如果已經修改尚未送出,也未放入暫存區,視為已修改狀态。如果已經添加進暫存區,視為暫存狀态。
2.4 安裝Git
要開始使用Git,首先得安裝Git。你有幾種方式獲得Git;兩種主要的方式是從源代碼安裝以及選擇你的平台上的安裝包。
2.4.1 從源代碼安裝
如果可以的話,從源代碼安裝Git非常有用,因為這樣可以安裝最近的版本。Git的每個版本會包含有用的UI增強元素,如果你覺得從源碼編譯軟體是一件很舒服的事情,那麼你就可以擷取最新的版本。
要安裝Git,你需要安裝以下的依賴包:curl、zlib、openssl、expat和libiconv。例如如果你的系統有yum或者apt-get,你就可以使用下面的指令安裝依賴包:
$ yum install curl-devel expat-devel gettext-devel \
openssl-devel zlib-devel
$ apt-get install libcurl4-gnutls-dev libexpat1-dev gettext \
libz-dev libssl-dev
如果所有需要的包已經具備,你可以繼續然後抓取Git官方網站上最近的快照:
http://git-scm.com/download
然後,編譯并且安裝:
$ tar -zxf git-1.7.2.2.tar.gz
$ cd git-1.7.2.2
$ make prefix=/usr/local all
$ sudo make prefix=/usr/local install
完成之後你可以通過Git獲得Git:
$ git clone git://git.kernel.org/pub/scm/git/git.git
2.4.2 在Linux上安裝
如果你要在Linux通過二進制包安裝Git,你可以使用你的系統發行版自帶的基本的包管理工具安裝,如果你在Fedora,你可以使用yum:
$ yum install git-core
如果你在一個基于Debian的發行版,例如Ubuntu,試試apt-get:
$ apt-get install git-core
2.4.3 在Mac上安裝
在Mac上有兩種簡單地方式安裝Git。最簡單的是使用圖形Git安裝器,可以從Google Code的頁面下載下傳,見圖1-7:
http://code.google.com/p/git-osx-installer
另一個主流的方式是使用MacPorts(http://www.macports.org)。如果你安裝了MacPorts,你可以這樣安裝Git:
$ sudo port install git-core +svn +doc +bash_completion +gitweb
你不需要添加所有的附加包,如果你需要使用Git處理SVN倉庫,那麼你需要加上+svn包。
2.4.4 在Windows上安裝
在Windows上安裝Git非常簡單,msysGit項目有一個簡單地安裝過程,隻需要下載下傳安裝檔案并運作就好了:
http://code.google.com/p/msysgit
安裝完之後,包含指令行版本和标準GUI。
2.5 初次使用Git的設定
既然你已經安裝了Git,你可能想對自己的Git環境做一些個性化設定。這些事情你隻需要做一次,及時更新這些設定依然會保留。當然你也可以随後通過指令再次改變這些設定。
Git有一個叫做git config的工具,他可以讓你擷取并且設定配置變量來設定Git看起來怎樣,怎麼操作。這些變量可以在三個地方存儲:
- /etc/gitconfig檔案:包含适用于系統中每個使用者以及他們所有的倉庫的變量值。如果你傳--system選項給git config,那麼Git會從這個檔案讀寫。
- ~/.gitconfig檔案:隻對目前使用者生效。如果你傳遞--global給git config,那麼Git會從這個檔案中讀寫。
- 在任意一個你所工作的倉庫的Git目錄下面的配置檔案(.git/config):隻對目前這個倉庫生效。沒一個級别的配置會覆寫上一級别的配置。
在Windows中。Git回去$HOME中去找配置檔案(C:\Documents and
Settings\$USER),它還會去查找/etc/gitconfig。
2.5.1 你的身份
設定Git的第一件事就是需要設定你的名字和email,這一點很重要,因為每次送出,Git都需要使用這些資訊。這些資訊不可變的傳遞進commit的資訊裡:
$ git config --global user.name "John Doe"
$ git config --global user.email [email protected]
再說一遍,如果你傳遞--global選項,那麼這件事情你隻需要做一次就可以了,當你在這個系統上做任何事情Git都會自動的去使用這些資訊。如果你需要對特定的項目用另一個姓名或者email去覆寫之前的設定,你可以運作上面的指令不加--global選項。
2.5.2 你的編輯器
既然身份資訊已經确立下來了,接下來你可以配置當需要輸入資訊時,Git預設使用的文本編輯器了。預設情況下,Git會使用你的系統的預設編輯器,一般來說是Vi或者Vim。如果你想使用其他的編輯器,例如Emacs,你可以這樣:
$ git config --global core.editor emacs
2.5.3 你的Diff工具
另外一個有用的選項你可能需要配置的是預設的diff工具用來解析合并的沖突,假設你想使用vimdiff,你可以:
$ git config --global merge.tool vimdiff
Git支援kdiff3、tkdiff、meld、xxdiff、emerge、vimdiff、gvimdiff、ecmerge、和opendiff。你也可以設定一個自定義的工具,詳見第七章相關内容。
2.5.4 檢查你的設定
如果你需要檢查一下你的設定,可以使用git config --list指令來列出所有的設定:
$ git config --list
user.name=Scott Chacon
color.status=auto
color.branch=auto
color.interactive=auto
color.diff=auto
...
你可能會看到一些重複的key這是因為Git會從不同的檔案中去讀取key值。在這個例子中,Git使用每個key的最後一個值。
你還可以通過git config {key}來檢視特定key的值。
$ git config user.name
Scott Chacon
2.6 擷取幫助
如果你在使用Git的時候需要幫助,有三種方法可以檢視任何Git指令的幫助文檔:
$ git help <verb>
$ git <verb> --help
$ man git-<verb>
你可以運作下面的指令來獲得config指令的manpage:
$ git help config
這些指令非常好,因為即使離線狀态你也可以使用它們。如果本書和這些manpage還不夠用來解決你的問題,你可以試試Freenode IRC伺服器上的#git或者#github頻道。這些頻道裡面有很多熟悉Git的人,他們往往會願意幫助你。
2.7 小結
你需要對Git是什麼以及為什麼Git與其他一些你正在使用的集中式版本控制系統不同有一些基本的了解。你現在應該已經有了一個Git版本并且已經設定了你的個人資訊,是時候學點Git基礎了。