卷2:第6章 Git

2018-02-24 15:55 更新

作者:Susan Potter,翻譯:張吉

原文:http://www.aosabook.org/en/git.html

6.1 Git概述

Git能夠讓不同的協(xié)作者通過(guò)一個(gè)點(diǎn)對(duì)點(diǎn)的倉(cāng)庫(kù)網(wǎng)絡(luò)對(duì)數(shù)據(jù)內(nèi)容(通常是代碼,當(dāng)然不僅限于代碼)進(jìn)行維護(hù)。它支持分布式的工作流程,能夠讓數(shù)據(jù)內(nèi)容臨時(shí)分離,并最終合并到一起。

本章將闡述Git的內(nèi)部實(shí)現(xiàn)是如何提供以上功能的,以及它和其他版本控制系統(tǒng)(VCS)的區(qū)別。

6.2 Git起源

為了更好地理解Git的設(shè)計(jì)思想,我們有必要先了解一下Git項(xiàng)目的發(fā)源地——Linux內(nèi)核開發(fā)社區(qū)——所面臨的問(wèn)題。

Linux內(nèi)核開發(fā)與其他商業(yè)軟件項(xiàng)目有很大不同,因?yàn)樗拈_發(fā)者眾多,且每個(gè)開發(fā)者的參與程度和對(duì)Linux內(nèi)核代碼的理解有很大差異。多年以來(lái),內(nèi)核代碼一直都是以Tar壓縮文件以及補(bǔ)丁的形式維護(hù)的,而當(dāng)時(shí)的核心開發(fā)團(tuán)隊(duì)一直在尋找一個(gè)能夠滿足他們各方面需求的版本控制系統(tǒng)。

Git就是在這樣的背景下于2005年作為一款開源軟件誕生的。當(dāng)時(shí),Linux內(nèi)核代碼通過(guò)兩種版本控制系統(tǒng)進(jìn)行維護(hù),BitKeeper和CVS,分別由兩組核心開發(fā)團(tuán)隊(duì)使用。BitKeeper相較于當(dāng)時(shí)頗為流行的CVS,提供了一種不同的歷史展示方式。

當(dāng)BitKeeper的所有者BitMover決定收回Linux內(nèi)核開發(fā)人員的使用許可時(shí),Linux Torvalds緊急開啟了一個(gè)項(xiàng)目,也就是后來(lái)的Git。一開始,他通過(guò)編寫一組Shell腳本來(lái)幫助他將郵件中的補(bǔ)丁按順序應(yīng)用到代碼中。這組原始腳本能夠在代碼合并過(guò)程中迅速中斷,讓維護(hù)者能夠進(jìn)行人工干預(yù),修改代碼,然后繼續(xù)合并。

從項(xiàng)目開始之初,Torvalds就為Git制定了一個(gè)目標(biāo)——要和CVS的做法完全相反——同時(shí)還包含了以下三條設(shè)計(jì)目標(biāo):

  • 支持分布式的協(xié)作流程,類似BitKeeper
  • 預(yù)防代碼錯(cuò)亂
  • 高性能

這些設(shè)計(jì)目標(biāo)都被實(shí)現(xiàn)了,我會(huì)在下文中通過(guò)解析Git的各種做法來(lái)闡述,包括在內(nèi)容管理中使用有向無(wú)環(huán)圖(DAG),頭指針引用,對(duì)象模型,遠(yuǎn)程協(xié)議,以及Git如何追蹤合并樹。

雖然Git設(shè)計(jì)之初受到了很多BitKeeper的影響,但是兩者還是有根本上的區(qū)別的,如Git提供了更多分布式和本地開發(fā)流程,這點(diǎn)是BitKeeper做不到的。Monotone,2003年啟動(dòng)的一個(gè)開源分布式版本控制系統(tǒng),也對(duì)Git的早期開發(fā)產(chǎn)生了影響。

分布式版本控制系統(tǒng)在提供更靈活的工作流程的同時(shí),往往會(huì)增加它的復(fù)雜程度。分布式模型的獨(dú)特優(yōu)點(diǎn)有:

  • 能夠線下進(jìn)行增量提交
  • 開發(fā)者可以決定自己的代碼何時(shí)能夠開放出來(lái)
  • 能夠線下瀏覽歷史
  • 可以將工作成果發(fā)布到不同的倉(cāng)庫(kù),以不同的分支、不同的提交粒度展現(xiàn)出來(lái)

在Git項(xiàng)目的開發(fā)期間,誕生了其他三個(gè)開源分布式版本控制系統(tǒng)(其中Mercurial可以參見《開源軟件架構(gòu)》的第一卷)。這些分布式版本控制系統(tǒng)(dVCS)都提供了非常靈活的工作流程,這是先前的集中式版本控制系統(tǒng)做不到的。注意:Subversion有一款插件名為SVK,由不同的開發(fā)者維護(hù),提供了服務(wù)器之間的同步功能。

目前流行的dVCS包括Bazaar, Darcs, Fossil, Git, Mercurial, 以及Veracity。

6.3 版本控制系統(tǒng)的設(shè)計(jì)

現(xiàn)在讓我們回過(guò)頭來(lái)看看Git之外的其他版本控制系統(tǒng)是如何設(shè)計(jì)的。通過(guò)比較他們和Git之間的區(qū)別,可以幫助我們?nèi)ダ斫釭it在架構(gòu)設(shè)計(jì)中的選擇。

版本控制系統(tǒng)通常有三項(xiàng)核心功能(需求):

  • 保存內(nèi)容
  • 記錄變更歷史(包括具體的合并信息)
  • 向協(xié)作者分發(fā)內(nèi)容和變更歷史

注意:第三項(xiàng)并不是所有版本控制系統(tǒng)的核心功能。

保存內(nèi)容

在VCS中保存內(nèi)容,最普遍的做法是保存增量的修改,或使用有向無(wú)環(huán)圖(DAG)。

增量修改可以反映出兩個(gè)版本之間的內(nèi)容差異,以及一些額外的信息。使用有向無(wú)環(huán)圖保存內(nèi)容則是將特定對(duì)象構(gòu)造成一種樹狀結(jié)構(gòu),作為某一次提交的快照保存下來(lái)(樹狀結(jié)構(gòu)中未發(fā)生變化的對(duì)象是可以重用的)。Git使用有向無(wú)環(huán)圖來(lái)保存內(nèi)容,它所使用的不同對(duì)象類型會(huì)在本文的“對(duì)象數(shù)據(jù)庫(kù)”一節(jié)中有所描述。

提交和合并的歷史

在保存歷史、記錄變化方面,大部分VCS使用以下方式之一:

  • 線性歷史
  • 有向無(wú)環(huán)圖

Git使用的還是有向無(wú)環(huán)圖,這次則是用來(lái)保存歷史。每次提交包含了它父節(jié)點(diǎn)的元信息——Git中的一次提交可以擁有0個(gè)或多個(gè)父節(jié)點(diǎn)(理論上沒有個(gè)數(shù)限制)。例如,Git倉(cāng)庫(kù)的第一次提交就沒有父節(jié)點(diǎn),而一次三頭合并則有三個(gè)父節(jié)點(diǎn)。

Git和SVN線性提交的另一個(gè)重要區(qū)別是Git可以直接進(jìn)行分支的創(chuàng)建,并記錄下大部分合并歷史。

libgit2。一開始它并不流行,直到一個(gè)名叫Vincent Marti的學(xué)生在谷歌編程夏令營(yíng)中使用了它。從那以后,Vincent和Github持續(xù)對(duì)libgit2類庫(kù)貢獻(xiàn)代碼,并為其他語(yǔ)言編寫了相應(yīng)類庫(kù),包括Ruby,Python,PHP,.NET,Lua,Object-C等。

Shawn Pearce還開啟了一個(gè)名為JGit的BSD項(xiàng)目,使用純Java語(yǔ)言實(shí)現(xiàn),能夠?qū)it版本庫(kù)進(jìn)行基本的操作。該類庫(kù)現(xiàn)在由Eclipse基金會(huì)維護(hù),用于Eclipse IDE的Git插件中。

還有其他一些有趣的周邊項(xiàng)目,帶有實(shí)驗(yàn)性質(zhì),使用各類數(shù)據(jù)源來(lái)保存Git對(duì)象,如:

  • jgit_cassandra?使用Apache Cassandra作為Git對(duì)象數(shù)據(jù)庫(kù)。它是一種混合型的數(shù)據(jù)源,提供了動(dòng)態(tài)的BigTable式的數(shù)據(jù)模型。
  • jgit_hbase?能夠?qū)it對(duì)象保存在HBase中,一種KV型分布式數(shù)據(jù)庫(kù)。
  • libgit2-backends?由libgit2項(xiàng)目衍生而來(lái),致力于提供其他種類的數(shù)據(jù)源,如Memcached,Redis,SQLite,MySQL。

以上這些都是獨(dú)立于Git核心工具包之外的項(xiàng)目。

如你所見,我們可以用各種方式來(lái)使用Git,它的表現(xiàn)形式不再只有命令行這一種了,而是成為一種版本控制系統(tǒng)的協(xié)議。

在本文撰寫之時(shí),這些項(xiàng)目都還沒有發(fā)布穩(wěn)定版本,所以還是有很多工作要做,但整體看來(lái)未來(lái)是光明的。

6.10 經(jīng)驗(yàn)教訓(xùn)

在軟件設(shè)計(jì)中,任何一個(gè)決定都有正反兩面。作為一個(gè)在日常工作中大量使用Git,并且還為Git對(duì)象數(shù)據(jù)庫(kù)開發(fā)了周邊軟件的程序員,我覺得Git目前的組織方式非常棒。因此,下文提到的“經(jīng)驗(yàn)教訓(xùn)”更多的是來(lái)自其他開發(fā)者對(duì)于Git目前設(shè)計(jì)方式的不滿,主要?dú)w咎于Git核心開發(fā)者當(dāng)初做出的決定。

最常見的問(wèn)題在于Git相較于其他CVS不能很好地和IDE進(jìn)行整合,因?yàn)镚it是基于工具包設(shè)計(jì)的,整合起來(lái)會(huì)比較具有挑戰(zhàn)性。

早期Git的實(shí)現(xiàn)是采用shell腳本的方式,不能很好地跨平臺(tái),特別是對(duì)于Windows操作系統(tǒng)。雖然我相信Git開發(fā)者不會(huì)因?yàn)檫@個(gè)問(wèn)題而寢食難安,但這的確阻礙了Git在大型公司內(nèi)的推廣?,F(xiàn)在,有一個(gè)名為Git for Windows的項(xiàng)目由志愿者發(fā)起,及時(shí)地將最新的Git開發(fā)成果移植到Windows平臺(tái)上。

Git工具包的設(shè)計(jì)方式所帶來(lái)的另一個(gè)間接影響是,他的底層命令繁多,會(huì)讓初學(xué)者陷入困境,難以理解Git出錯(cuò)時(shí)拋出的異常信息,最后無(wú)可適從。這就使得Git在某些開發(fā)團(tuán)隊(duì)中的推廣受到阻礙。

即便如此,我仍然對(duì)Git核心項(xiàng)目以及其周邊項(xiàng)目的開發(fā)充滿信心。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)