
1 版本控制系統(tǒng)
版本控制系統(tǒng)是一種記錄一個或若干個文件內(nèi)容變化,以便將來查閱特定版本修訂情況的系統(tǒng)。一般情況下,對軟件源代碼的文件進行版本控制,但實際上,你可以對任何類型的文件進行版本控制。
有了版本控制系統(tǒng),你就可以將某個文件回溯到之前的狀態(tài),甚至將整個項目都回退到過去某個時間點的狀態(tài),可以比較文件的變化細節(jié),查出最后是誰修改了哪個地方,從而找出導致怪異問題出現(xiàn)的原因,又是誰在何時報告了某個功能缺陷等等。
1.1 本地版本控制系統(tǒng)
許多人習慣用復制整個項目目錄的方式來保存不同的版本,或許還會改名加上備份時間以示區(qū)別。這么做唯一的好處就是簡單,但是特別容易犯錯。有時候會混淆所在的工作目錄,一不小心就會寫錯文件或者覆蓋意想外的文件。
在早期,為了解決這個問題,人們就開發(fā)了許多本地版本控制系統(tǒng),這些系統(tǒng)大都是采用某種簡單的數(shù)據(jù)庫來記錄文件的歷次更新差異。

1.2 集中式版本控制系統(tǒng)
接下來又遇到一個問題,如何讓在不同系統(tǒng)上的開發(fā)者協(xié)同工作?于是,集中化的版本控制系統(tǒng)(Centralized Version Control Systems,簡稱 CVCS)應運而生。這類系統(tǒng),諸如 CVS、Subversion 以及 Perforce 等,都有一個單一、集中管理的服務器,上面保存著所有文件的修訂版本,而協(xié)同工作的開發(fā)者都通過客戶端連到這臺服務器,取出最新的文件或者提交更新。多年以來,這已成為版本控制系統(tǒng)的標準做法。

現(xiàn)在,每個人都可以在一定程度上看到項目中的其他人正在做些什么。而管理員也可以輕松地管理每個開發(fā)者的權限,并且管理一個 CVCS 要遠比在各個客戶端上維護本地數(shù)據(jù)庫來得輕松容易。
然而這么做,最顯而易見的缺點是中央服務器的單點故障。如果宕機一小時,那么在這一小時內(nèi),誰都無法提交更新,也就無法協(xié)同工作。如果中心數(shù)據(jù)庫所在的磁盤發(fā)生損壞,又沒有做恰當備份,毫無疑問你將丟失所有數(shù)據(jù)——包括項目的整個變更歷史,只剩下開發(fā)者在各自機器上保留的單獨快照。本地版本控制系統(tǒng)也存在類似問題,只要整個項目的歷史記錄被保存在單一位置,就有丟失所有歷史更新記錄的風險。
1.3 分布式版本控制系統(tǒng)
為了消除單點故障風險,分布式版本控制系統(tǒng)(Distributed Version Control System,簡稱 DVCS)出現(xiàn)了。在這類系統(tǒng)中,像 Git、Mercurial、Bazaar 以及 Darcs 等,客戶端并不只提取最新版本的文件快照,而是把代碼倉庫完整地鏡像下來。這么一來,任何一處協(xié)同工作用到的服務器發(fā)生故障,都可以用任何一個鏡像出來的本地倉庫恢復。因為每一次的克隆操作,實際上都是一次對代碼倉庫的完整備份。

更進一步,這類系統(tǒng)大都可以指定和多個不同的遠端代碼倉庫進行交互。籍此,你就可以在同一個項目中,分別和不同工作小組的人相互協(xié)作。你可以根據(jù)需要設定不同的協(xié)作流程,比如層次模型式的工作流,而這在集中式系統(tǒng)中是無法實現(xiàn)的。
2 Git 簡史
Linux 內(nèi)核開源項目有著為數(shù)眾廣的開發(fā)者。絕大多數(shù)的 Linux 內(nèi)核維護時間與精力都花在了提交補丁和保存歸檔的繁瑣事務上(1991-2002年間)。所以到了 2002 年,整個項目組開始啟用一個專有的分布式版本控制系統(tǒng) BitKeeper 來管理和維護代碼。
2005 年,開發(fā) BitKeeper 的商業(yè)公司同 Linux 內(nèi)核開源社區(qū)的合作關系結(jié)束,他們收回了 Linux 內(nèi)核社區(qū)免費使用 BitKeeper 的權力。這就迫使Linux 開源社區(qū)開發(fā)出自己的版本控制系統(tǒng)。他們對新的系統(tǒng)制訂了若干目標:
- 速度
- 簡單的設計
- 對非線性開發(fā)模式的強力支持(允許成千上萬個并行開發(fā)的分支)
- 完全分布式
- 有能力高效管理類似 Linux 內(nèi)核一樣的超大規(guī)模項目(速度和數(shù)據(jù)量)
自誕生于 2005 年以來,Git 日臻成熟完善,在高度易用的同時,仍然保留著初期設定的目標。它的操作速度很快,極其適合管理大項目,有著令人難以置信的非線性分支管理能力。
3 Git 基礎
3.1 直接記錄快照,而非差異比較
Git 和集中式版本控制系統(tǒng)(Subversion)的主要差別在于對待數(shù)據(jù)的方法上。從概念上來區(qū)分,集中式版本控制系統(tǒng)以文件變更列表的方式存儲信息。這些系統(tǒng)把保存的信息看作是一組基本文件和每個文件隨時間推移而逐步累積的差異。

Git 是把數(shù)據(jù)看作是對小型文件系統(tǒng)的一組快照。每次提交更新或保存項目狀態(tài)時,Git 會把當時的全部文件制作成一個快照并保存這個快照的索引。如果文件沒有修改,Git 只保留一個鏈接指向之前存儲的文件(節(jié)省空間)。Git 對待數(shù)據(jù)的方式是快照流。

這是 Git 與其它版本控制系統(tǒng)的重要區(qū)別。它更像是一個小型的文件系統(tǒng),提供了許多以此為基礎構建的工具。
3.2 幾乎所有操作都在本地執(zhí)行
在 Git 中的絕大多數(shù)操作都只需要訪問本地文件和資源。相對于所有操作都在有網(wǎng)絡延時開銷的集中式版本控制系統(tǒng)而言,Git 在操作上具有顯著的速度優(yōu)勢。因為在本地磁盤上就保存著項目的完整歷史,所以大部分操作看起來像是瞬間就可以完成的。
舉個例子,要瀏覽項目的歷史,Git 不需要連到服務器去獲取歷史,然后再顯示出來——它只需直接從本地數(shù)據(jù)庫中讀取。所以你能立即看到項目歷史。如果你想查看當前版本與一個月前的版本之間引入的修改,Git 會查找到一個月前的文件做一次本地的差異計算。操作都在本地,速度能不快嗎O(∩_∩)O~
如果你在飛機或火車上想做些開發(fā)工作,仍然可以愉快地提交,直到有網(wǎng)絡連接時再上傳。用 Subversion 或 CVS,你能修改文件,但不能向服務器提交修改(因為沒有網(wǎng)絡咯)。
3.3 保證完整性
所有數(shù)據(jù)在存儲前都計算校驗和,然后以校驗和來引用。這個功能建構在 Git 底層。如果在傳送過程中丟失信息或文件損壞,Git 就能發(fā)現(xiàn)這些問題。
Git 使用 SHA-1 散列(hash,哈希)計算校驗和。這是一個由 40 個十六進制字符(0-9 和 a-f)組成字符串,基于 Git 中文件的內(nèi)容或目錄結(jié)構計算出來。SHA-1 哈希后的結(jié)果看起來像是這樣:
24b9da6552252987aa493b52f8696cd6d3b00373
實際上,Git 的數(shù)據(jù)庫中保存的信息都是以文件內(nèi)容的哈希值來索引的,而不是文件名。
3.4 一般只添加數(shù)據(jù)
執(zhí)行的 Git 操作,幾乎只往 Git 數(shù)據(jù)庫中增加數(shù)據(jù)。一旦提交快照到 Git 中,就可以避免數(shù)據(jù)丟失。
3.5 文件的三種狀態(tài)
文件有三種狀態(tài):
- 已提交(committed)- 表示數(shù)據(jù)已經(jīng)安全地保存在本地數(shù)據(jù)庫中。
- 已修改(modified)- 表示修改了文件,但還沒保存到數(shù)據(jù)庫中。
- 已暫存(staged)- 表示對一個已修改文件的當前版本做了標記,它會被包含在下一次提交的快照中。
由此引入 項目的三種工作區(qū)域:Git 倉庫、工作目錄以及暫存區(qū)域。

倉庫目錄用來保存項目的元數(shù)據(jù)和對象數(shù)據(jù)庫。這是 Git 中最重要的部分,從其它計算機克隆倉庫時,拷貝的就是這里的數(shù)據(jù)。
工作目錄是對項目的某個版本獨立提取出來的內(nèi)容。這些從 Git 倉庫的壓縮數(shù)據(jù)庫中提取出來的文件,放在磁盤上供使用或修改。
暫存區(qū)域是一個文件,保存了下次將要提交的文件列表信息,一般在 Git 倉庫目錄中。也可稱為索引。
基本的 Git 工作流程如下:
- 在工作目錄中修改文件。
- 暫存文件,將文件的快照放入暫存區(qū)域。
- 提交更新,找到暫存區(qū)域的文件,將快照永久性存儲到 Git 倉庫目錄。
如果 Git 目錄中保存著的特定版本文件,就屬于已提交狀態(tài)。如果作了修改并已放入暫存區(qū)域,就屬于已暫存狀態(tài)。如果自上次取出后,作了修改但還沒有放到暫存區(qū)域,就是已修改狀態(tài)。
4 命令行
在我們的介紹中,將使用命令行模式。這是因為,只有在命令行模式下才能執(zhí)行 Git 的 所有 命令,而大多數(shù)的 GUI 軟件只實現(xiàn)了 Git 所有功能的一個子集以降低操作難度。所以如果你學會了在命令行下如何操作,那么在操作 GUI 軟件也將得心應手O(∩_∩)O~
5 安裝 Git
5.1 在 Linux 上安裝
可以使用發(fā)行版包含的基礎軟件包管理工具來安裝。如果以
centos7 上為例,你可以使用 yum:
$ sudo yum install git
如果在基于 Debian 的發(fā)行版上,請使用 apt-get:
$ sudo apt-get install git
5.2 在 Mac 上安裝
在 Mac 上安裝 Git 有多種方式。最簡單的方法是安裝 Xcode Command Line Tools。Mavericks (10.9) 或更高版本的系統(tǒng)中,在 Terminal 里嘗試首次運行 git 命令即可。如果沒有安裝過命令行開發(fā)者工具,將會提示安裝。
如果想安裝更新的版本,可以使用二進制安裝程序。官方維護的 OSX Git 安裝程序可以在 Git 官方網(wǎng)站下載,網(wǎng)址為 http://git-scm.com/download/mac。
也可以將它作為 GitHub for Mac 的一部分來安裝。它們的圖形化 Git 工具有一個安裝命令行工具的選項??梢詮?GitHub for Mac 網(wǎng)站下載該工具,網(wǎng)址為 http://mac.github.com。
5.3 在 Windows 上安裝
在 Windows 上安裝 Git 也有幾種安裝方法。官方版本可以在 Git 官方網(wǎng)站下載。打開 http://gitscm.com/download/win,下載會自動開始。要注意這是一個名為 Git for Windows 的項目(也叫做msysGit),和 Git 是分別獨立的項目;更多信息請訪問 http://msysgit.github.io/。
另一個簡單的方法是安裝 GitHub for Windows。該安裝程序包含圖形化和命令行版本的 Git。它也能支持 Powershell,提供了穩(wěn)定的憑證緩存和健全的 CRLF 設置。可以在 GitHub for Windows 網(wǎng)站下載,網(wǎng)址為 http://windows.github.com。
6 初次運行 Git 前的配置
安裝好 Git 之后,就可以定制你的 Git 環(huán)境。每臺計算機上只需要配置一次,程序升級時會保留配置信息。
Git 自帶一個 git config 的工具來幫助設置控制 Git 外觀和行為的配置變量。這些變量存儲在三個不同的位置:
- /etc/gitconfig 文件:包含系統(tǒng)上每一個用戶及他們倉庫的通用配置。 如果使用帶有 --system 選項的 git config 時,它會從此文件讀寫配置變量。
- ~/.gitconfig 或 ~/.config/git/config 文件:只針對當前用戶。 可以傳遞 --global 選項讓 Git 讀寫此文件。
- 當前使用倉庫的 Git 目錄中的 config 文件(就是 .git/config):只針對這個倉庫。
每一個級別覆蓋上一級別的配置,所以 .git/config 的配置變量會覆蓋 /etc/gitconfig 中的配置變量。
在 Windows 系統(tǒng)中,Git 會查找 $HOME 目錄下(一般情況下是
C:\Users$USER)的 .gitconfig 文件。Git 同樣也會尋找 /etc/gitconfig 文件,但只限于 MSys 的根目錄下,即安裝 Git 時所選的目標路徑位置。
6.1 用戶信息
安裝完 Git 后,首先要設置你的用戶名稱與郵件地址。每一次 Git 的提交都會使用這些信息,且不可更改:
$ git config --global user.name "Deniro Li"
$ git config --global user.email lisq@example.com
再次強調(diào),如果使用了 --global 選項,那么該命令只需要運行一次,因為之后無論做什么, Git 都會使用這些信息。當你想針對特定項目使用不同的用戶名稱與郵件地址時,可以在那個項目目錄下運行沒有 --global 選項的命令來配置。
很多 GUI 工具都會在第一次運行時幫助你配置這些信息。
6.2 文本編輯器
現(xiàn)在可以配置默認文本編輯器了,當 Git 需要你輸入信息時會調(diào)用它。如果未配置,Git 會使用操作系統(tǒng)默認的文本編輯器,通常是 Vim。如果你想使用不同的文本編輯器,例如 Emacs,可以這樣做:
$ git config --global core.editor emacs
6.3 檢查配置信息
如果想要檢查你的配置,可以使用 git config --list 命令來列出所有 Git 當時能找到的配置。

你可能會看到重復的變量名,因為 Git 會從不同的文件中讀取同一個配置(例如:/etc/gitconfig 與~/.gitconfig)。這種情況下,Git 會使用它找到的每一個變量的最后一個配置。
也可以通過輸入 git config <key>: 來檢查 Git 的某一項配置:

7 獲取幫助
使用 Git 時,如果需要獲取幫助,有三種方法可以找到 Git 命令的使用手冊:
$ git help <verb>
$ git <verb> --help
$ man git-<verb
舉個例子,如果要想獲得 config 命令的手冊,可以執(zhí)行:
$ git help config

這些命令很好用,因為你隨時隨地都可以使用而無需聯(lián)網(wǎng)。如果你覺得手冊還不夠用,可以嘗試在Freenode IRC 服務器( irc.freenode.net )的 #git 或 #github 頻道尋求幫助。這些頻道經(jīng)常有上百人在線,他們都精通 Git 并且樂于助人。