2006 年 11 月 06 日
版
本控制系統(tǒng)或資源管理系統(tǒng)是現(xiàn)代軟件開發(fā)的一個(gè)重要方面。不使用版本控制系統(tǒng)就如同超速駕駛一輛汽車:很刺激,也可能會(huì)更快抵達(dá)目的地,但事故卻在所難
免。本文概述了軟件配置管理(SCM)系統(tǒng)及其優(yōu)勢(shì),內(nèi)容涵蓋 CVS、Subversion、Arch 和 Git。本文還討論了最常見的 SCM
體系結(jié)構(gòu)。本文在最后給出了新出現(xiàn)的一些方法及這些方法與先前方法的區(qū)別。
什么是軟件配置管理?
在學(xué)校學(xué)習(xí)的重要工具中,通常不會(huì) 包含 SCM。軟件(或資源)控制,正如其名字所暗示的那樣,是一種工具和一種相關(guān)的過(guò)程,而這種過(guò)程被用于維護(hù)源代碼及其演進(jìn)。SCM 提供的主要功能如下:
- 在存儲(chǔ)庫(kù)(repository)中維護(hù)一個(gè)文件。
- 在存儲(chǔ)庫(kù)中維護(hù)文件的修訂。
- 檢測(cè)源更改沖突并為多個(gè)開發(fā)人員的環(huán)境提供合并。
- 跟蹤變更的發(fā)起方。
- 為了實(shí)現(xiàn)一致、可重復(fù)的構(gòu)建提供文件(相關(guān)修訂)的配置管理。
 |
SCM 的適用性
資源控制 主要是指源代碼和相關(guān)文件的控制,而資源管理 則可應(yīng)用于任何類型的資源。包含超文本標(biāo)記語(yǔ)言(HTML)和二進(jìn)制圖像文件、一般文本文檔或其他任何文件的 Web 站點(diǎn)是 SCM 系統(tǒng)進(jìn)行修訂控制的對(duì)象。
|
|
所以,SCM 允許您控制存儲(chǔ)庫(kù)中的一組文件并跟蹤這些文件的修訂。其他開發(fā)人員更改了存儲(chǔ)庫(kù)中的這些文件后,SCM
會(huì)標(biāo)識(shí)出這些變更與您所做的變更之間存在的沖突,然后自動(dòng)將其合并或通知您存在沖突。這個(gè)功能非常重要,因?yàn)樗试S多個(gè)開發(fā)人員修改同一組文件。SCM
還能跟蹤出誰(shuí)做了何種變更。SCM 還允許您將文件按邏輯劃分為相關(guān)的文件組,比如組成軟件圖像或可執(zhí)行文件的源文件。
SCM 的術(shù)語(yǔ)
在深入研究 SCM 體系結(jié)構(gòu)的類型和細(xì)節(jié)之前,先要熟悉一下術(shù)語(yǔ)的含義。存儲(chǔ)庫(kù) 是文件存儲(chǔ)和管理的中心位置(有時(shí)又被稱為樹)。從存儲(chǔ)庫(kù)中取出文件放到本地系統(tǒng)的工作文件夾的過(guò)程被稱作簽出。如果變更了本地文件而又想同步變更存儲(chǔ)庫(kù),就需要執(zhí)行更新。如果要將變更后的文件簽入到存儲(chǔ)庫(kù),就需執(zhí)行提交。如果所變更的文件先前已經(jīng)被變更并已由別人提交,則會(huì)發(fā)生合并,表明兩組變更集將會(huì)被合并在一起。若由于變更沖突的原因不能合并時(shí),則必已發(fā)生了沖突。在此情況下,提交被拒絕,并要求開發(fā)人員手工合并變更。當(dāng)提交了變更之后,就會(huì)創(chuàng)建此文件的一個(gè)新的修訂。
一個(gè)或多個(gè)開發(fā)人員可以對(duì)主樹(存儲(chǔ)庫(kù)的當(dāng)前頭)或位于主樹旁的單個(gè)的分支進(jìn)行操作。這就讓開發(fā)人員可以操作分支而不會(huì)影響到主樹。當(dāng)分支穩(wěn)定后,再將分支與主樹進(jìn)行合并。
要標(biāo)記源樹演進(jìn)過(guò)程中的重要階段,可以對(duì)一組文件修訂應(yīng)用標(biāo)簽。這會(huì)將這組文件組合成一個(gè)有用的集合(有時(shí)會(huì)用作針對(duì)于惟一構(gòu)建的文件的一個(gè)發(fā)布)。
體系結(jié)構(gòu)
各種 SCM 間有許多的差異,其中有兩種最基本的區(qū)別很值得研究:
- 集中式存儲(chǔ)庫(kù)與分布式存儲(chǔ)庫(kù)
- 變更集模型與快照模型
集中式存儲(chǔ)庫(kù)與分布式存儲(chǔ)庫(kù)
現(xiàn)代 SCM 體系結(jié)構(gòu)的最為重要的差異之一是存儲(chǔ)庫(kù)是集中式的還是分布式(分散的)。當(dāng)前最為常見的體系結(jié)構(gòu)是集中式存儲(chǔ)庫(kù)。這個(gè)星型 體系結(jié)構(gòu)由中心的源存儲(chǔ)庫(kù)和工作于這個(gè)存儲(chǔ)庫(kù)的多個(gè)開發(fā)人員組成(參見圖 1)。開發(fā)人員從中心存儲(chǔ)庫(kù)簽出源代碼到本地的沙箱內(nèi),進(jìn)行變更后,將它提交回中心存儲(chǔ)庫(kù)。其他開發(fā)人員就可以再訪問(wèn)這些變更。
圖 1. 在集中式體系結(jié)構(gòu)中,所有開發(fā)人員都通過(guò)同一個(gè)中心存儲(chǔ)庫(kù)進(jìn)行工作
中心存儲(chǔ)庫(kù)也可以創(chuàng)建分支,允許多個(gè)開發(fā)人員協(xié)作于針對(duì)位于存儲(chǔ)庫(kù)(但必須在 mainline 或 tip 之外)的資源的一組變更。
分布式體系結(jié)構(gòu)則允許開發(fā)人員為其變更創(chuàng)建其自己本地的存儲(chǔ)庫(kù)。本地開發(fā)人員的存儲(chǔ)庫(kù)與原始的存儲(chǔ)庫(kù)(已被分布)很相似。主要的區(qū)別是:在集中化的
方式中,變更是在沙箱內(nèi)完成的,而在分布式方法中則允許開發(fā)人員工作于分離的存儲(chǔ)庫(kù)。開發(fā)人員進(jìn)行變更、提交變更到其本地的存儲(chǔ)庫(kù),之后,在不影響主干的
前提下,與其他開發(fā)人員的變更合并。這樣,本地開發(fā)人員就使得變更集對(duì)上線(upline)開發(fā)人員可用(參見圖 2)。
圖 2. 在分散體系結(jié)構(gòu)中,開發(fā)人員通過(guò)其各自的存儲(chǔ)庫(kù)員同步工作
分散體系結(jié)構(gòu)很有意思,因?yàn)樗试S不同的開發(fā)人員在對(duì)等網(wǎng)絡(luò)內(nèi)同步工作。當(dāng)工作準(zhǔn)備好(最好是穩(wěn)定)后,開發(fā)人員可以分發(fā)變更集(或修補(bǔ))以使他人也可以使用這些特性。這是當(dāng)今許多開源系統(tǒng)的模型,包括 Linux? 內(nèi)核。
變更集模型與快照模型
早先的和現(xiàn)代的 SCM 的體系結(jié)構(gòu)的另一個(gè)有趣的區(qū)別是 delta 變更的存儲(chǔ)方式。它們理論上是相同的,且產(chǎn)生的結(jié)果也相同,但在修訂的存儲(chǔ)方式上二者卻大不相同。
在快照模型中,整個(gè)存儲(chǔ)庫(kù)的每個(gè)修訂(帶優(yōu)化以減少樹的大?。┑娜课募急淮鎯?chǔ)。而在變更集模型中,只有 delta 被存儲(chǔ)于修訂之間,這樣就創(chuàng)建了一個(gè)精簡(jiǎn)的存儲(chǔ)庫(kù)(參見圖 3)。
圖 3. 快照模型和變更集模型各有所長(zhǎng)
從圖 3
可以看出,模型不同但結(jié)果卻相同。在快照模型中,可以快速獲得修訂,但需要更多的空間來(lái)存儲(chǔ)它們。而變更集模型需要的空間少,但需要更多時(shí)間來(lái)獲得某個(gè)修
訂,原因是 delta 必須應(yīng)用于基本修訂。在本文后面的部分將介紹如何建立優(yōu)化來(lái)最小化必須要應(yīng)用的 delta 的數(shù)量。
示例 SCM
讓我們來(lái)看一下按體系結(jié)構(gòu)(集中或分布)劃分的一些 SCM。您很快就會(huì)看到,其中一些 SCM 支持兩種模型。
CVS
并發(fā)版本系統(tǒng)(Concurrent Versions System,CVS)是當(dāng)今最為常用的
SCM。它是一種集中式的解決方案,采用了快照模型,開發(fā)人員使用集中式的存儲(chǔ)庫(kù)來(lái)進(jìn)行軟件的協(xié)作開發(fā)。CVS 十分常見而且是 Linux
發(fā)布版的一部分。其簡(jiǎn)單和方便的語(yǔ)法(對(duì)大多數(shù)人而言)使其迅速成為了多個(gè)或單個(gè)開發(fā)人員 SCM 的一種理想選擇。
清單 1 給出了一組 CVS 命令示例和簡(jiǎn)短的相關(guān)描述。要獲得關(guān)于 CVS 的更多信息,請(qǐng)參閱 參考資料 部分。
清單 1. CVS 命令示例
# Create a new repository
cvs -d /home/user/new_repository init
# Connect to the central repository
export CVSROOT=:pserver:user@example.com:/cvs_root
# Check out a sandbox for module project from the central repository
cvs checkout project
# Update a local sandbox from the central repository
cvs update
# Check in changes from the local sandbox to the central repository
cvs commit
# Add new files to the local sandbox (need to be committed)
cvs add <file/subdirectory>
# Show changes made in the local sandbox
cvs diff
|
對(duì)于喜歡用指向-單擊方式操作的用戶,CVS 提供了許多開源的圖形化前端以供使用,包括 WinCVS 和 TortoiseCVS(集成了 Microsoft? Windows Explorer)。
盡管 CVS 被廣泛采用,但它仍然有一些不足之處。CVS 不允許重命名文件,而且對(duì)一些特殊文件(如 symlink)的支持不是很好。變更可以按文件跟蹤,而非按變更本身,這點(diǎn)十分討厭。合并有時(shí)也會(huì)出現(xiàn)問(wèn)題(CVS 內(nèi)部會(huì)為此使用 diff3)。
然而,CVS 總體而言還是很有用的,能夠?qū)崿F(xiàn)其需要實(shí)現(xiàn)的任務(wù),而且所有主流的平臺(tái)都支持 CVS。如果喜歡用 CVS 而又想回避其缺點(diǎn),則可以考慮使用 Subversion。
Subversion
Subversion(SVN)是為了替代 CVS 而設(shè)計(jì)的,消除了 CVS 原有的問(wèn)題和缺點(diǎn)。與 CVS 一樣,Subversion
也是一種集中化的解決方案,采用的是快照模型。它的命令也模仿了 CVS 的,但增加了一些對(duì)諸如刪除文件、重命名文件或恢復(fù)為原始文件等的處理功能。
Subversion 還允許遠(yuǎn)程訪問(wèn),可以采用很多協(xié)議,比如超文本傳輸協(xié)議 (HTTP)、安全 HTTP或定制的 SVN 協(xié)議,此協(xié)議還支持通過(guò) Secure Shell (SSH)的隧道技術(shù)。
清單 2 給出了 Subversion 所支持的一些命令及 CVS 中所沒(méi)有的一些擴(kuò)展。要獲得關(guān)于 Subversion 的更多信息,請(qǐng)參閱 參考資料 部分。很明顯,Subversion 的命令集和 CVS 的很相似,這使它極受 CVS 用戶的歡迎。
清單 2. Subversion 的命令示例
# Create a new repository
svnadmin create /home/user/new_repository
# Check out a sandbox from the central repository
svn checkout file:///server/svn/existing_repository new_repository
# Update a local sandbox from the central repository
svn update
# Check in changes from the local sandbox to the central repository
svn commit
# Add new files to the local sandbox (need to be committed)
svn add <file/subdirectory>
# Show changes made in the local sandbox
svn diff
# Rename a file in the local sandbox (requires commit to the repository)
svn rename <old_file> <new_file>
# Remove files (also removed from repository, requires commit)
svn delete <file/subdirectory>
|
與 CVS 一樣,Subversion 集成了一些圖形化的前端如
ViewCVS 和 TortoiseSVN。另外也有一些工具可以把 CVS 存儲(chǔ)庫(kù)轉(zhuǎn)化為
Subversion(例如 cvs2svn.py),但這些工具并不能處理復(fù)雜版本的分支和標(biāo)記。和許多開源項(xiàng)目一樣,隨著時(shí)間的推移,這種情況會(huì)有所改變。Subversion 還集成了 TortoiseMerge
作為一個(gè)單獨(dú)的查看器和修補(bǔ)程序。
Subversion 解決了許多讓 CVS 用戶困擾的問(wèn)題,比如特殊文件的版本化和自動(dòng)的提交和簽出。如果您喜歡用 CVS 和集中式存儲(chǔ)庫(kù)的方式,那么
Subversion 就是您所需的 SCM。
現(xiàn)在讓我們先放下對(duì)集中方式的討論,看看被人們視為 SCM 未來(lái)的協(xié)作式分散存儲(chǔ)庫(kù)。
Arch
Arch 是分散 SCM 的規(guī)范,它提供許多不同的實(shí)現(xiàn),包括 ArX、Bazaar、GNU arch 和 Larch。Arch 不僅可以作為一種分散 SCM 運(yùn)作,如 圖 2 所示,還可使用變更集模型(參見 圖 3)。
Arch SCM
是開源開發(fā)的一種很流行的方法,因?yàn)殚_發(fā)人員可在單獨(dú)的存儲(chǔ)庫(kù)上進(jìn)行開發(fā),同時(shí)又能夠控制全部資源。這是因?yàn)榉植际酱鎯?chǔ)庫(kù)就是具有修訂控制的實(shí)際存儲(chǔ)庫(kù)。
可以在本地存儲(chǔ)庫(kù)利用變更創(chuàng)建一個(gè)修補(bǔ)來(lái)供上游的開發(fā)人員使用。這就是分散模型的真正的強(qiáng)勢(shì)所在。
與 Subversion 相似,Arch 解決了 CVS 中所存在的許多問(wèn)題,包括元數(shù)據(jù)的變更,例如修訂文件許可、處理文件刪除和重命名以及自動(dòng)的簽入(將簽入組在一起而非作為單獨(dú)的文件)。
清單 3 中顯示了 Arch SCM 中的一些常見命令,還給出了 GNU arch,因?yàn)樗怯?Arch 的
設(shè)計(jì)者 Tom Lord 開發(fā)的。GNU arch 提供了 SCM 應(yīng)有的一些基本功能,包括 Subversion 中的一些新特性。
清單 3. GNU arch (tla) 的命令示例
# Register a public archive
tla register-archive http://www./arch
# Check out a local repository from the upstream repository
tla get project@--dev/project--stable myproject
# Update from the local repository
tla update
# Check in changes to the local repository
tla commit
# Add new files to the local repository (need to be committed)
tla add <file>
# Show changes made in the local repository (patch format)
tla what-changed
# Rename a file in the local repository (requires commit to the repository)
tla mv <old_file> <new_file>
# Remove files (also removed from repository, requires commit)
tla rm <file>
|
Arch 還允許用 star-merge 合并來(lái)自上游存儲(chǔ)庫(kù)的變更。為了最小化必須應(yīng)用到基本修訂的修補(bǔ)的數(shù)量(根據(jù)變更集模型),
cacherev 命令將會(huì)在存儲(chǔ)庫(kù)中創(chuàng)建基本修訂的一個(gè)新的快照。
創(chuàng)建基本修訂的一個(gè)新快照
Arch 的優(yōu)勢(shì)之一是雖然它是為分散操作所設(shè)計(jì)的,但也可以用于集中存儲(chǔ)庫(kù)范例。
tla 用戶對(duì)其不滿之處是它太過(guò)復(fù)雜。其他的 Arch 實(shí)現(xiàn),例如 baz 則非常簡(jiǎn)單。如果 tla 不能滿足要求,可以嘗試使用后者。
現(xiàn)在讓我們來(lái)看一下最后一個(gè)分散式的 SCM,它由 Linux 內(nèi)核的維護(hù)者 Linus Torvalds 本人編寫。
Git
Git SCM 由 Linus Torvalds 開發(fā),用來(lái)替代
Bitkeeper SCM(參閱 參考資料 部分)。
它非常簡(jiǎn)單,是一種分散式的基于變更集的 SCM 且用作 Linux 內(nèi)核的 SCM。它使用文件組模型而非跟蹤單個(gè)的文件。使用 SHA1 壓縮并混編變更集以驗(yàn)證其完整性(參見清單 4)。
清單 4. Git 的命令示例
# Get a Git repository (first time)
git clone rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git linux-2.6
rsync -a --progress rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/ .git/
# Update a Git repository from the defined upstream Git repository
git pull rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
# Checkout from the Git repository into the local working repository
git checkout
# Update from the local Git repositor3
git-update-cache
# Commit changes to the local Git repository
git commit
# Add new files to the local repository
git-update-cache --add <file>
# Show changes made to the local working directory
git diff
# Remove files (requires commit)
git-update-cache --remove <file>
|
Git SCM 在其自己的 Git 存儲(chǔ)庫(kù)內(nèi)是自托管的,這意味著您必須引導(dǎo) Git 來(lái)將其安裝到本機(jī)。Git 的命令集與您到目前為止看到的那些命令十分類似,而且相對(duì)簡(jiǎn)單。
您可能會(huì)問(wèn):“為什么不使用現(xiàn)有的 SCM 中的一種呢?” 問(wèn)得很好。
Git 非常有趣,吸引著許多
Linux 內(nèi)核黑客,所以它很可能成為下一個(gè)主流的 SCM。Linus 將 Git 描述為一個(gè)高速的目錄內(nèi)容管理器,雖然它所做的工作不多但完成得十分高效。
收益
無(wú)論您使用何種 SCM,都會(huì)獲得一些普遍的收益。使用
SCM,可以跟蹤文件中的變更來(lái)判斷變更對(duì)軟件的影響程度。當(dāng)發(fā)生不正確的變更時(shí),可以發(fā)現(xiàn)這些變更并將它們恢復(fù)回原始資源中??梢越M合文件修訂集并標(biāo)記
它們來(lái)制作發(fā)布,而發(fā)布又可以在任何時(shí)間簽出以供重復(fù)構(gòu)建代碼的特定發(fā)布(SCM 的要求)。
不管使用集中式存儲(chǔ)庫(kù)還是分布式存儲(chǔ)庫(kù),使用快照模型還是變更集模型,所帶來(lái)的收益都是相同的。因?yàn)槿魏维F(xiàn)代軟件開發(fā)項(xiàng)目都必須要有 SCM,所以越早越多地使用它們就會(huì)受益越多。
前景展望
本文只討論了現(xiàn)在最為常用的 SCM 的一些最基礎(chǔ)的知識(shí)。還有許多其他的開源 SCM 可以使用,例如
Aegis、Bazaar-NG、DARCS 和 Monotone。當(dāng)然,SCM
也引起了一些爭(zhēng)論,而這些爭(zhēng)論通常很難有正確的答案。如果使用一種工具后效率極高,那就使用這種工具吧!SCM
大多時(shí)候都用在團(tuán)隊(duì)開發(fā)的情況下,而很少用于孤立的個(gè)人開發(fā)的環(huán)境中(除非您是個(gè)獨(dú)斷專行的老板,喜歡自己做所有決定)。所以,您盡可以嘗試所有的可能性
來(lái)熟悉一些不同的風(fēng)格。SCM 是軟件開發(fā)中的必需工具,也是您的開發(fā)工具箱中的必備部分。
參考資料
學(xué)習(xí)
關(guān)于作者
 |
|
 |
M. Tim Jones 是一名嵌入式軟件工程師,他是 GNU/Linux Application Programming、AI Application Programming 和 BSD Sockets Programming from a Multilanguage Perspective 等書籍的作者。他的工程背景非常廣泛,從同步宇宙飛船的內(nèi)核開發(fā)到嵌入式架構(gòu)設(shè)計(jì),再到網(wǎng)絡(luò)協(xié)議的開發(fā)。Tim 是 Emulex Corp. 的一名顧問(wèn)工程師。
|
|