天天看點

版本控制之道——使用Git_樣章

精彩内容搶先看——

第1章

Git的版本控制之道

Version Control the Git Way

版本控制系統(Version Control System,VCS)可以幫助我們記錄和跟蹤項目中各檔案内容的修改變化。它最簡單的、手工的實作形式是:複制檔案以備份,在備份檔案的檔案名中添加上時間和日期。

然而,為了效率起見,我們希望這類操作在某種程度上是自動的。這是我們需要版本控制工具的原因,這類工具能夠自動地備份和跟蹤項目中所有代碼的修改。

分布式版本控制系統(Distributed version control system,DVCS)也是這樣,它的主要目标仍然是幫助記錄和跟蹤項目中所做的修改。而它與傳統版本控制系統的差別在于,開發人員互相同步修改内容的方式不同。

本章将研究什麼是版本控制系統,以及分布式版本控制系統——特别是Git——與傳統的集中式版本控制系統的差別。

本章内容如下:

l  什麼是版本庫。

l  如何判斷該存儲些什麼。

l  什麼是工作目錄樹。

l  如何管理和同步檔案。

l  如何跟蹤項目、目錄和檔案的内容。

l  如何使用标簽來辨別項目裡程碑。

l  如何使用分支來跟蹤并行開發。

l  什麼是合并。

l  Git中的鎖機制。

這些論題全都是圍繞着版本庫展開的。是以,讓我們從學習版本庫開始。

1.1  版本庫

The Repository

版本庫(Repository)是版本控制系統用來存儲所有曆史資料的地方。大多數版本控制系統在版本庫中存儲各個檔案的目前狀态、曆史修改時間、誰做的修改,以及修改的原因。

版本控制系統就好比是銀行保險箱,而它所儲存的曆史資訊就好比對賬單。每當存入一筆存款時,或者用版本控制系統的行話來說,每當進行一次送出(Commit)的時候,版本控制系統就會在“對賬單”上添加一個條目,并且把送出的内容儲存在版本庫裡。

在早期的版本控制系統中,必須登入版本庫所在的伺服器,才能通路這些版本庫。這會帶來可擴充性方面的問題。而較新的版本控制系統,比如CVS和Subversion,解決了這樣的問題。這類版本控制系統允許程式員通過網絡來擷取版本庫中的代碼,并在修改後送出回來。

這類版本控制系統屬于集中式版本庫(Centralized Repository)模式。在這種模式中,所有的程式員都會把他們的改動送出到伺服器上的一個公共版本庫中。具體來說,每一個程式員在本地有一個工作目錄樹,其内容是該版本庫中最新的代碼。當他們在工作目錄樹中完成代碼修改後,就把改動送出回該版本庫中。

這類使用集中式版本庫的版本控制系統與早期的直接通路式版本控制系統相比,有很大進步,但仍有其局限性。首先,在本地工作目錄樹中,隻能看到代碼的最新版本。如果想查詢曆史修改記錄,就必須與伺服器上的版本庫打交道。這就帶來另一個問題:同遠端的版本庫連接配接,通常須要使用網絡。

在這個“永不斷線”的寬帶網際網路時代,我們幾乎忘記了有時候不能上網。以本書的寫作過程為例,有時候是在家中,有時候是在咖啡店裡,有時候是在飛機上,還有的時候是在長途汽車上。甚至,本書最後的修訂是在密蘇裡州奧紮克族印第安人的小木屋裡。

如果使用分布式版本控制系統,就不會遇到不能上網所帶來的問題。這是以Git為代表的分布式版本控制系統最大的優勢。使用分布式版本控制系統,每個人都會在本地有自己的版本庫,而不是連接配接到伺服器上的一個公共的版本庫。所有的曆史記錄都存儲在本地的版本庫中。向版本庫送出代碼無須連接配接遠端版本庫,而是記錄在本地的版本庫中。

讓我們回到銀行保險箱這個類比看一下。集中式版本控制系統就好比是程式員們共用一個保險箱。而分布式版本控制系統就好像是每個程式員都有他自己的個人保險箱。

那麼,在分布式版本控制系統中,程式員之間如何傳遞各自的修改,如何同步呢?程式員還是将修改上傳到項目主版本庫。這有兩種實作方法:可以通過Git的“推入”(Push)操作直接把修改上傳到主版本庫,也可以生成包含少量修改的更新檔包,把更新檔包送出給項目維護人員,再由項目維護人員更新主版本庫。

1.2  版本庫中存儲什麼

What Should You Store?

對此問題的簡短回答:所有内容。

稍微複雜一些的回答是:存儲項目開發所必需的所有内容。這使得程式員能夠修改代碼,編譯建構,使項目前進。顯然,首先要存儲的是項目源代碼,否則,既無法修複缺陷也無法繼續開發新功能。

大多數項目都有一些建構檔案。常見的有:Makefile、Rakefile及Ant的build.xml。這些檔案都要放入版本庫,以友善源代碼編譯建構。

版本庫中其他常見存儲内容還有:配置檔案樣例、各類文檔、程式使用的圖檔,當然還有單元測試腳本。

要判斷哪些内容應該納入版本控制很簡單,自己想一下,“如果沒有某樣東西,我能在這個項目中工作嗎?”如果答案是否定的,那麼這樣東西就應當納入版本控制。

但凡事皆有例外:項目中使用的開發工具,通常不用放到版本控制中去。比如,Ant的“build.xml”應該放到版本控制中,但Ant工具本身不需要。

這個例外并不是這麼嚴格的。可以考慮把Ant、JUnit等工具都放入版本庫中,以保證大家都使用相同版本的工具。當然,最好把它們與項目本身的内容分開存放。

1.3  工作目錄樹

Working Trees

至此,我們已經介紹了版本庫,以及應該在其中存儲哪些内容。下面将介紹工作目錄樹(Working Tree),也就是程式員進行程式開發的地方。

工作目錄樹是版本庫的一個“斷面視圖”。它包括了開發該項目所需要的全部檔案,包括源代碼檔案、建構檔案、單元測試檔案等。

一些版本控制系統把工作目錄樹稱為工作拷貝(Working Copy)。Git新手經常會混淆Git中的版本庫和工作目錄樹。因為在Subversion等傳統的版本控制工具中,工作目錄在本地,版本庫在伺服器上,而Git中并非如此。

在Git中,版本庫不在伺服器上,而存儲在本地工作目錄樹的“.git”目錄中。這意味着,要想知道曆史資訊,隻和本地的版本庫打交道即可,無須與伺服器上的版本庫通信。

那麼,工作目錄樹最初是怎麼建立出來的呢?有兩個方法:第一個方法是用Git相關指令初始化版本庫,也就是生成“.git”目錄,于是“.git”目錄的父目錄就成了工作目錄樹。第二個方法是克隆(Clone)一個已有的版本庫,也就連帶建立了相應的工作目錄樹。

克隆一個已有的版本庫,就是建立該版本庫的一個拷貝,并把版本庫中主分支(Master Branch)的内容檢出(Check out)到工作目錄樹。在Git中,檢出是指把工作目錄樹更新,使其内容與版本庫中某個特定的曆史版本相同。關于克隆版本庫,将在7.2節“克隆遠端版本庫”(第103頁)中詳細介紹。

跟蹤變更是版本控制系統(CVS)的核心功能。到目前為止,我們已經介紹了版本庫和工作目錄樹——也就是版本庫的一個“斷面視圖”——但還沒有講解變更相關的話題,這将在下一節中介紹。