# 版本控制
一個*版本控制系統*(或*修訂控制系統*)是跟蹤和控制項目文件變更的技術與實踐的組合,包括源代碼、文檔和網頁。如果你以前從來沒有使用過版本控制,那你最好趕快找一個有經驗的人加入。現今,所有的人都希望你的項目源代碼存放在版本控制下,如果不使用版本控制,人們將會輕視項目。
版本控制如此廣泛的原因是因為它實際上能幫助運營一個項目的所有方面:內部開發者交流、發布管理、Bug管理、代碼穩定性和試驗開發投入,以及對某個變更所屬開發者的歸因和授權。版本控制系統為這些領域提供了一個集中的協調力量。版本控制的核心是*變更管理*:識別對項目文件的每一個不相關的變更,使用元數據例如變更的日期和作者來注解每個變更,之后無論使用什么方法,任何人詢問時,重放這個事實。這是一種變更為信息基本單元的交流機制。
這個部分不會討論使用版本控制的所有方面。它是如此包羅萬象,我們不得在本書不時的提及。因此,我們會通過促進協作開發的方式,專注于版本控制系統的選擇和設置。
### 版本控制詞匯表
如果你沒有用過版本控制,本書不會教你如何使用,但是如果沒有一些關鍵術語,我們就無法討論。這些術語獨立于任何特定的版本控制系統:它們是網絡交互的基本名詞和動詞,將會在本書剩下的部分廣泛使用。即使這個世界上沒有版本控制,變更管理的問題也會存在,這些術語為我們簡明的討論這些問題提供了一種語言。
**“版本”對“修訂版本”**
單詞*版本(version)*有時候作為“修訂版本”的同義詞使用,但是在本書我不會這樣使用,因為這太容易與一個軟件的版本混淆—也就是軟件的發布或版本號,例如在“版本 1.0(Version 1.0)”。不管怎樣,因為短語“版本控制”已經標準化了,所以我會繼續將其視為“修訂版本控制”和“變更控制”的同義詞。
*提交(commit)*
對項目做出一個變更;更正式的,以此方式在版本控制數據庫存儲一個變更,可以成為項目以后發布的一部分。 “提交”可以作為名詞或動詞。作為名詞,從本質上講可以看作是“變更(change)”同義詞。例如:“我剛剛為報告的Mac OS X上的服務器宕機Bug提交了一個修訂。Jay,你能評審一下提交并看一下我有沒有誤用內存分配嗎?”
*日志信息(log message)*
每次提交所附的注釋,描述了提交的性質和目的。日志信息是任何項目最重要的文檔:它是單個代碼變更的高度技術語言與特性、Bug修訂和項目進展這類更面向用戶的語言的橋梁。本節的后半部分,我們會關注將日志信息發布給適當讀者的方法;另外,[Chapter?6, *交流*](# "Chapter?6.?交流")的[the section called “編制法律的傳統”](# "編制法律的傳統")將會討論鼓勵貢獻者填寫簡明和有用日志信息的方法。
*更新(update)*
請求將其他人的變更(提交)和項目的本地拷貝進行組合;也就是將你的拷貝“保持最新”。這是一個非常常見的操作;大多數開發者每天都會多次更新代碼,因此,可以確認他們運行的代碼與別人的相同,因此他們看到一個Bug,他們可以確信它還沒有被修正。例如:“嗨,我發現索引代碼一直會丟掉最后一個字節。這是一個新的bug嗎?”“是的,但已經在上周修正了—更新一下,一定是好了。”
*版本庫(repository)*
一個存放變更的數據庫。一些版本控制是集中式的:有一個單獨的主版本庫,會存放項目的所有變更。也有一些分布式的系統:每個開發者都有自己的版本庫,變更可以在版本庫之間任意交換。版本控制系統跟蹤了變更之間的依賴關系,當需要發布時,確認一部分變更集進入發布。集中式還是分布式的問題也是一場不朽的軟件開發圣戰;也要防止落入在你的項目列表中討論這個問題的陷阱。
*檢出(checkout)*
從版本庫獲取項目拷貝的過程。一個檢出通常會產生一個叫做“工作拷貝”(看后面)的目錄樹,可以從這個目錄將變更提交回原來的版本庫。在一些分布式的版本控制系統,每個工作拷貝本身都是一個版本庫,變更可以推出(拖入)到任何愿意接受的版本庫。
*工作拷貝(working copy)*
一個包含項目源代碼文件或者網頁及其他文檔的開發者的私有目錄樹。一個工作拷貝也可能會包含由版本控制系統管理的元數據信息,可以說明工作拷貝所對應的版本庫,以及所展現文件的“修訂版本(看后面)”等等。通常情況下,每個開發者都有自己的工作拷貝,他可以在其中進行變更以及測試,并提交。
*修訂版本(revision)*, *變更(change)*, *變更集(changeset)*
一個“修訂版本”通常是一個特定文件或目錄的具體化身。例如,如果開始時一個項目有一個文件F,修訂版本是6,然后如果有一個文件對文件F提交了一個變更,那么就會產生F的修訂版本7。一些系統也使用“修訂版本”,“變更”或“變更集”來引用作為一個邏輯概念的一組變更。
這些術語在不同的版本控制系統可能有不同的技術含義,但是大意基本相同:他們提供了一個方法可以精確的描述一個文件或一組文件歷史中的精確位置(比方說,恰恰在一個Bug修正之前或之后)。例如:“她在修訂版本10修正了那個”或者“他在文件foo.c的修訂版本10修正了那個。”
當一個人在不指定特定修訂版本的時候談論一個文件或一組文件時,通常假定是指最近的修訂版本。
*差異(diff)*
變更的文本化展現。一個差異顯示了哪些行發生了怎樣的改變,以及圍繞上下文兩側的幾行。一個已經熟悉代碼的開發者通常可以閱讀區別,并理解變更完成的事情,甚至定位Bug。
*標簽(tag)*
一組特定修訂版本的文件的標簽。標簽通常用來保存人們感興趣的項目快照。例如,為每個公開發布使用標簽,這樣人們就可以從版本控制系統獲取發布對應的文件/修訂版本。常見的標簽名稱有`Release_1_0`、`Delivery_00456`等等。
*分支(branch)*
項目的一個拷貝,在版本控制之下,但卻是孤立的,所以分支上的變更不會影響項目的其他部分,或者相反,除非你故意將變更“合并”過去(看后面)。分支也被稱為“開發線(lines of development)”。即使當一個項目沒有明確的分支,開發也可以被認為是發生在“主分支”,也稱為“主線”或“*主干(trunk)*”。
分支提供了一個將開發線隔離的方法。例如,一個分支可以用來進行對于主干不夠穩定的實驗開發。或者一個分支可以用來穩定新的發布。在發布過程中,有規律的開發可以繼續不受干擾的在版本庫的主線進行;與此同時,在發布分支,除非經過發布管理員的確認,不允許任何變更。通過這種方式,讓發布不必干擾正在進行的開發工作。關于分支的詳細討論見本章后面的[the section called “使用分支來避免瓶頸”](# "使用分支來避免瓶頸")。
*合并(又名搬運)(merge, a.k.a. port)*
用來將變更從一個分支搬運到另一個。這包括從主干合并到分支,或者相反。實際上,這是最常見的合并類型;在兩個非主分支之間搬運變更的情況很少見。關于此類合并的更多信息可以看[the section called “信息單一性”](# "信息單一性")。
“合并”也有另一種相關的含義:也就是當兩個人對于同一個文件作出沒有交疊的變更時,版本控制系統所作的事情。因為兩個變更沒有互相干擾,當一個人更新其拷貝中的這個文件(已經包含他自己的變更)時,其他人的變更會自動合并進去。這非常常見,特別是當多個人編輯同一代碼時。當兩個變更*確實*交疊了,結果就是“沖突”了;看下面。
*沖突(conflict)*
當兩個人希望對于代碼的同一個地方作出不同的修改時。所有的版本控制系統會自動監測到沖突,并至少讓一個人意識到他們的變更與其他人的沖突了。這依賴于*解決(resolve)*沖突的人,以及與版本控制系統解決的交流。
*鎖定(lock)*
對于某個文件或目錄進行排他變更聲明的方法。例如,“我現在不能對網頁文件提交任何變更。似乎Alfred已經鎖定了所有文件,因為他要修改背景圖片。”不是所有的版本控制系統都提供了鎖定能力,它們并不都需要使用鎖定特性。這是因為平行,同時開發是行為準則,而將人們鎖定在文件之外違背了這個思想。
需要鎖定才能提交的版本控制系統,我們稱之使用*鎖定-修改-解鎖*模型。而其他的我們稱之為*拷貝-修改-合并*模型。兩種模型的一個完美的深入解釋和比較可以看[http://svnbook.red-bean.com/svnbook-1.0/ch02s02.html](http://svnbook.red-bean.com/svnbook-1.0/ch02s02.html)。通常情況下,拷貝-修改-合并適合于開源開發,在本書討論的版本控制工具都支持這個模型。
### 選擇一個版本控制系統
在寫本文的時候,自由軟件世界中兩個最流行的版本控制系統是*并行版本系統*(*CVS*,[http://www.cvshome.org/](http://www.cvshome.org/))和*Subversion*(*SVN*,[http://subversion.tigris.org/](http://subversion.tigris.org/))。
CVS已經存在很長時間了。大多數有經驗的開發者已經熟悉了它,它或多或少滿足了你的需要,而且因為它已經流行了很長時間了,你可能不會陷入它是否為正確選擇的爭論。CVS有一些缺點。它不支持簡單的引用多個文件的變更;它不支持版本控制下的文件重命名和拷貝(這種情況下如果你需要識別出項目開始后的代碼樹,會非常頭痛);它對合并的支持很弱;它處理大文件和二進制文件不佳;以及在操作很多文件時操作會非常慢。
CVS的這些Bug都不是致命的,所以它一直非常流行。然而,最近幾年Subversion逐漸被人們所接受,特別是在新創建的項目中。[[15](#)]如果你新開始一個項目,我推薦Subversion。
在另一方面,因為我參與了Subversion項目,我的客觀性有理由值得懷疑。在最近幾年,許多新的開源版本控制系統已經出現。[Appendix?A, *自由版本控制系統*](# "Appendix?A.?自由版本控制系統")列出了所有我知道的,大體上根據流行性排序。就像列表說明的,決定使用何種版本控制系統可能成為一項終身的研究項目。有可能你也會省掉選擇的過程,因為你的主站已經做出了選擇。但如果你必須做出選擇,請咨詢那些有經驗的人,然后選擇一個并使用起來。任何穩定的產品狀態的版本控制系統可以實現;你不必擔心會做出災難性的錯誤決定。如果你無法下決心,那就Subversion吧。它學起來相對簡單,在近幾年里還應該保持標準的地位。
### 使用版本控制系統
這一部分的建議不針對任何特定版本控制系統,它們都應當可以簡單的實現。詳細信息請參考特定系統的文檔。
### 版本化所有的東西
不要僅僅將項目的源代碼納入到版本控制下,也應該包括網頁、文檔、FAQ、設計注釋和任何人們希望編輯的內容。讓他們與源代碼盡量接近,在同一個版本庫樹中。任何值得寫下來的信息都應該納入版本控制—也就是任何可能會變更的信息。不會發生變更的東西都應該歸檔,而非版本化。例如,一個郵件一旦發布,就不會變更;因此,將其版本化沒有任何意義(除非它成為一個較大的、進化文檔的一部份)。
在一個地方版本化所有的東西的原因非常重要,這樣人們只需要學習一種提交變更的方式。例如,經常是一個貢獻者開始編輯一個網頁或者文檔,然后接著做一些代碼變更。當項目對于所有的提交使用相同的提交方式時,人們只需要學習一次。一起版本化所有的東西也意味著隨著文檔的更新,新特性可以一起提交,而代碼分支時也是對文檔分支等等。
不要將*生成的文件*置入版本控制。那些應該不是可編輯的數據,因為它們是程序方式由其他文件產生的。例如,一些構建系統根據模板`configure.in`文件產生`configure`。為了改變`configure`,我們需要編輯`configure.in`,然后重新生成;因此,只有文件`configure.in`是“可編輯文件。”只版本化模板—如果你也版本化結果文件,人們在對模板進行修改后會不可避免的忘記重新生成它,結果的不一致會導致無休止的混淆。[[16](#)]
所有可編輯數據必須存放在版本控制下的規則也有一個不幸的例外:Bug跟蹤。Bug數據庫保存了大量的可編輯數據,但是因為技術原因不能將數據存放在版本控制系統。 (一些跟蹤工具有一些原始的版本控制特性,然而,獨立于項目的主版本庫。)
### 可瀏覽性
項目的版本庫應該能夠通過web瀏覽。這不僅是意味著瀏覽最新修訂的能力,也包括回到過去查看早先的版本,查看修訂之間的區別,以及閱讀針對特定變更的日志信息等等。
可瀏覽性非常重要,因為它是一個輕量級的項目數據門戶。如果不能通過web瀏覽版本庫,那一個人如果希望檢查特定的文件(例如,看一下某個bug修正是否已經進入代碼),他必須在本地安裝版本控制客戶端,這會讓一項只需要兩分鐘的任務變成一項半小時或更長的任務。
可瀏覽性也暗示了瀏覽文件特定修訂版本的標準URL,以及任意給定時間最近的修訂。在技術討論或向人們指明作為證據時這非常有用。例如我們不會說“關于調試服務器的提示,可以看你工作拷貝中的www/hacking.html”,而會說“關于調試服務器的提示,可以看*http://svn.collab.net/repos/svn/trunk/www/hacking.html*,”給定一個會一直指向`hacking.html`最新修訂的URL會更好。因為它不會導致混淆,也避免了用戶是否有最新工作拷貝的問題。
一些版本控制系統包含內置的版本庫瀏覽機制,而其他一些依賴于第三方的工具實現。這類工具有*ViewCVS*([http://viewcvs.sourceforge.net/](http://viewcvs.sourceforge.net/))、*CVSWeb*([http://www.freebsd.org/projects/cvsweb.html](http://www.freebsd.org/projects/cvsweb.html))以及*WebSVN*([http://websvn.tigris.org/](http://websvn.tigris.org/))。第一個工具可以支持CVS和Subversion,而第二個只支持CVS,而第三個只支持Subversion。
### 提交郵件
對版本庫的每一次提交應當能夠產生一個郵件,包含誰做出修改的、何時作出的修改、修改的文件和目錄以及為什么修改。郵件必須發送到專注于提交郵件的特別郵件列表,在郵件列表中能夠同普通人的郵件區分開來。必須鼓勵開發者和其他感興趣的參與者訂閱這個提交列表,這是從代碼級別來跟蹤項目的最有效方法。除了同級評審(見[the section called “實踐明顯的代碼評審”](# "實踐明顯的代碼評審"))這一明顯的技術益處,提交郵件幫助我們建立了一種社區意識,因為他們創建了一個共享環境,在其中人們可以對其他人也可見的事件(提交)作出反應。
設置提交郵件的具體方法依賴于你的版本控制系統,但通常有一些腳本或其他工具可以完成這個工作。如果你在尋找過程中遇到困難,可以查一下*鉤子(hooks)*的文檔,特別是*post-commit hook*,CVS中也稱作*loginfo hook*。Post-commit鉤子大意上就是對提交做出自動化的響應。這個鉤子會由每個提交出發,并提供關于提交的所有信息,你可以自由的使用這些信息做任何事情—例如,發送一個郵件。
通過預先包裝的提交郵件系統,你可能會希望修改一些默認的行為:
1.
一些提交郵件程序會在郵件中包含實際的區別,而不是提供在web上使用版本庫瀏覽系統查看變更的URL。雖然提供URL非常好,這樣后面就可以引用這個變更,但是在郵件本身中包含區別同樣*非常*重要。閱讀郵件已經成為人們的例行的一部分,如果變更的內容在提交郵件中,開發者可以立刻進行評審,不需要離開郵件閱讀器。如果他們需要點擊一個URL來評審變更,大多數人就不會作了,因為需要開始一個新動作,而不是延續一個已發生的動作。此外,如果評審者希望詢問變更的某些事情,可以直接選擇帶原文回復并注解區別,這樣就不必訪問網頁并辛勤的從web瀏覽器拷貝粘貼到郵件客戶端。
(當然,如果區別非常大,諸如大片的新代碼正文添加到了版本庫,那么省掉區別而只提供URL就比較有意義。大多數提交郵件程序可以自動執行這種限制。如果你的不支持,那包含區別也沒有關系,只是偶爾會有些大郵件,比完全沒有區別更好。便利的評審和回復是協作開發的奠基石,是否存在十分關鍵。)
1.
提交郵件必須將Reply-to頭設置為普通的開發郵件列表,而不是提交郵件列表。那是因為,當有人評審一個提交并撰寫了一個回復,這個回復應當自動轉向到人們的開發郵件列表,也就是通常人們討論技術問題的地方。有這么幾個原因。首先,你希望將技術討論保持在一個郵件列表中,因為這也是人們所期望的情況,而且這種情況下只需要搜索一個歸檔。其次,有一些感興趣的參與者可能沒有訂閱提交郵件列表。第三,提交郵件列表把自己當作一個監視提交的服務,而不是用來關注提交*并*偶爾進行技術討論。訂閱提交郵件列表的人除了提交郵件沒有訂閱其他東西;通過那個列表發送其他內容違反了隱含的契約。第四,人們經常寫程序來閱讀提交郵件列表并處理結果(例如為了顯示一個網頁)。這些程序預備好了處理一致格式的提交郵件,但與人寫的郵件不匹配。
請注意這里設置Reply-to的建議與本章前面[the section called “偉大的Reply-to辯論”](# "偉大的Reply-to辯論")中說的并不矛盾。對于信息的*發送者*來說,設置Reply-to非常正常。在這個情況下,發送者是版本控制系統本身,它設置Reply-to是為了說明回復的合適地方是開發郵件列表,而不是提交列表。
**CIA:另一種變更公示機制**
提交郵件不是傳播變更新聞的唯一方式。最近一種叫做CIA([http://cia.navi.cx/](http://cia.navi.cx/))的機制被開發了出來。CIA是一個實時提交統計信息的聚合器和分發器。CIA最流行的用處是發送提交提醒到IRC頻道,所以登陸到頻道的人都可以實時的看到發生的提交。盡管比提交郵件有較少的技術功效,因為觀察者不一定會在提交提醒彈出時就在頻道上,但是這項技術仍然有巨大的*社會*功效。人們得到了成為某個存在并活躍事務一部分的感覺,并且他們能夠感到正在發生的進展。
工作原理是通過你的post-commit鉤子調用CIA通知程序。通知器會將提交信息格式化為XML信息,并發送到中央服務器(通常是`cia.navi.cx`)。然后服務器將提交信息分發到其他論壇。
CIA也可以設置來發送[RSS](http://www.xml.com/pub/a/2002/12/18/dive-into-xml.html)供稿,更多細節可以看在[http://cia.navi.cx/](http://cia.navi.cx/)的文檔。
如果你想參考CIA的一個實例,將你的IRC客戶端指向`irc.freenode.net`,頻道`#commits`。
### 使用分支來避免瓶頸
非專家的版本控制用戶有時候會擔心分支與合并。這可能是CVS流行性的副作用:CVS對于分支和合并的接口和我們的知覺不太一致,所以很多人學著完全避免此類操作。
如果你周圍有很多這類人,立即下決心戰勝所有恐懼,并花時間學會如何分支和合并。它們不是什么困難的操作,一旦你習慣了,對于項目獲取更多的開發者這日益重要。
分支非常有價值,因為它將一項稀缺的資源—項目代碼的工作空間—變得充足。一般情況下,所有的開發者在同一個沙盒一起工作,建設同一座城堡。當某個人希望添加一個新的吊橋,但是不能確認其他人是否正在工作,分支使她被隔離到一個角落并做出嘗試成為可能。如果這種投入成功了,她可以要求其他開發者檢驗這個結果。如果所有人認可結果,他們可以告訴版本控制系統將吊橋從分支城堡移動(“合并”)到主城堡。
很容易看到這項能力是如何幫助協作開發的。人們需要自由嘗試新問題的感覺,而無須擔心干擾其他人的工作。同樣重要的是,當為了完成bug修正或發布穩定化(見<[Chapter?7, *打包、發布和日常開發*](# "Chapter?7.?打包、發布和日常開發")的[the section called “穩定發布版本”](# "穩定發布版本")和[the section called “維護多發布線”](# "維護多發布線")),代碼需要從日常的開發中分離出來時,所花費的時間數倍于無需擔心跟蹤一個移動目標的情況。
不受限制的使用分支,并鼓勵其他人也這樣做。但是要確保任何特定分支只保持必要的最短時間。任何活動分支都會讓社區分神。即使不是在分支工作的人也需要對此有所了解。這種了解是應該的,當然,對于分支的提交應該能和其他提交一樣發送提交郵件。但是分支不應該成為分割開發社區的機制。除了很少的例外,大多數分支最終必須合并回它們的主干并消失。
### 信息單一性
合并有一個推論:不要將同一個變更提交兩次。也就是一個修改只進入一次版本控制系統。變更的修訂(或一組修訂)可以在其進入版本控制系統之后擁有唯一標示。如果它需要應用到還沒有應用過的分支,那么它應該從最初的入口點合并到其他目標—而不是直接提交相同的文本,這樣雖然對代碼的效果是一樣的,但會導致我們無法進行精確的記錄和發布管理。
這個建議對于不同版本控制系統的實踐效果不盡相同。在一些系統,合并是特殊的事件,從根本上與提交不同,并包含他們自己的元數據。而另外一些系統,合并的結果就像其他變更一樣是提交到了系統,所以區別“合并提交”和“新變更提交”的主要方法是使用日志信息。在合并的日志信息中,不會再重復原始變更的信息。而只是指明這是一個合并,并提供原始變更的修訂版本,以及一段說明其效果的文字。如果有人希望看到完整的日志信息,她應該參考原來的修訂。
避免在提交之后再重復日志信息的原因非常重要,因為日志會在提交后被修改。如果變更日志在每個合并目標中重復,那有朝一日她修改了最初的信息,而那些重復還是會保持錯誤—混淆就會持續下去。
同樣的原理也適用于撤銷一個變更。如果一個變更從代碼中撤銷,那么這個撤銷的日志信息也應該僅僅是指明撤銷的是哪些特定的修訂版本,而*不是*描述撤銷過程中實際變更的代碼,因為變更的內容可以通過閱讀原來的日志信息和修訂獲得。當然,修訂版本日志信息也應當說明恢復變更的原因,但它不應該從原始變更日志信息復制任何東西。如果可能,回到原來的變更日志信息,并指明它已經撤銷了。
前面所說的都暗示了你應該使用一致的語法來引用這些修訂版本。這不僅僅在日志信息中有益,在郵件、Bug跟蹤和其他地方也同樣重要。如果你使用CVS,我建議使用“`path/to/file/in/project/tree:REV`”,其中的REV就是CVS的修訂版本好嗎,例如“1.76”。如果你使用Subversion,修訂版本1729的標準語法是“r1729”(文件路徑不是必需的,因為Subversion使用全局修訂版本號)。在其他系統中,也都有一些表達變更集的標準語法。無論對你的系統合適的語法是什么,鼓勵人們使用它們來引用變更。對變更名一致的表達方法可以幫助項目更簡單的紀錄(在[Chapter?6, *交流*](# "Chapter?6.?交流")和[Chapter?7, *打包、發布和日常開發*](# "Chapter?7.?打包、發布和日常開發")我們將會看到),而且因為許多紀錄是由志愿者完成的,它應該盡可能的簡單。
在[Chapter?7, *打包、發布和日常開發*](# "Chapter?7.?打包、發布和日常開發")的[the section called “發布和日常開發”](# "發布和日常開發")也有介紹。
### 授權
大多數版本控制系統提供了控制特定人可以從版本庫特定子區域提交的特性。根據這個原理,當人們手握錘子時,就開始到處找釘子,許多項目開始恣意使用這種特性,小心的為每個人只賦予他們被確認的權限,而不能在任何其他地方提交。 (看[Chapter?8, *管理志愿者*](# "Chapter?8.?管理志愿者")的[the section called “提交者”](# "提交者")來確認何人可以在何處提交。)
執行這樣嚴格的控制可能會有一些害處,一個寬松的政策也足夠好。一些項目會簡單得使用一個榮譽系統:當一個人被賦予提交權限,即使只是版本庫的一個子區域,他也會收到一個可以在項目所有地方可以提交的密碼。他們只是被告知要在自己的區域提交。請記住這里沒有真正的危險:在一個活躍的項目里,所有的提交會被審核。如果有人在不被允許的地方提交,其他人會發現這一點并說出來。如果這個變更需要被回退,很簡單—因為所有地變更都在版本控制之下,只需要回退。
這種寬松的方法有許多好處。首先,當開發者擴展了他們的活動范圍(如果他們一直在項目中,這是一個通常的情況),賦予更寬泛的權限無需額外的管理工作。一旦作出了這樣的決定,這個人就可以立刻在新區域提交。
第二,擴展可以以一種更細致的方式實現。通常情況下,區域X的提交者如果希望擴展到區域Y,他會通過發表對Y的一個補丁并尋求評審開始。如果對區域Y有提交權限的人看到這個補丁并確認,他可以直接讓提交者直接提交這個變更(當然也要在日志信息中提及評審者/確認者的名字)。這樣,這個提交就會成為實際編寫變更者的作品,無論從信息管理角度還是審計角度這樣都更好。
最后,可能是最重要的,使用榮譽系統來鼓勵互相尊重和信任的氛圍。給一個人對某一區域的訪問權限是對他們已經完成技術準備的證明—這是說:“我們已經看到了你已經具備了對某一領域做出修改的專業知識,那就繼續吧。”但設置嚴格的授權控制則是暗示:“我們不僅僅確認你專業知識的限制,而且我們對你的*目的*也保持懷疑。”如果可以避免的話,你一定不愿意做出這樣的評價。將一個人引入為項目的提交者是將其引入互相信任循環的機會。好的方法是給他們比期望所能發揮作用更大的權力,然后告訴他們是否保持在規定的限制內完全依賴于他們自己。
Subversion項目按照榮譽系統的方式已經運作超過4年了,在寫作時包含了33個完全的和43個部分提交者。系統實際強制的只是提交者和非提交者的區別;更細的劃分只由人為控制。但是我們從來沒有遇到故意在領域外提交的問題。只是有一兩次由于對個人提交權限范圍的誤解造成的錯誤,而且都能夠迅速和親切的得到解決。
很明顯,當自律的方式不夠實際時,那你就需要嚴格的授權控制。但這種情形非常少見。即使當有幾百萬行的代碼,以及數百或上千的開發者時,對于任何給定模塊的提交,也必須經過模塊上工作的人們的評審,而且他們可以識別出提交者是否得當。如果*沒有*有規律的提交評審,那么項目恐怕就會遇到比沒有授權系統更大的問題了。
歸納起來,不要在版本控制的授權系統上花費太多時間,除非你有特別的原因。復雜的授權系統不能帶來實際的好處,依賴人為控制有更多的優點。
當然,上面所說的并不意味著限制本身不重要。項目不應該鼓勵人們在不夠格的地方提交。此外,在很多項目中,完全(無限制)的提交訪問有一個特別的狀態:它隱含了項目范圍問題的投票權。提交訪問的政治方面將會在[Chapter?4, *社會和政治的基礎架構*](# "Chapter?4.?社會和政治的基礎架構")的[the section called “誰進行表決?”](# "誰進行表決?")詳細討論。
[[15](#)] 關于這種增長的證據可以看[http://cia.vc/stats/vcs](http://cia.vc/stats/vcs)和[http://subversion.tigris.org/svn-dav-securityspace-survey.html](http://subversion.tigris.org/svn-dav-securityspace-survey.html)。
[[16](#)] 對于版本化`configure`的不同意見,可以看Alexey Makhotkin的文章,在[http://versioncontrolblog.com/2007/01/08/configurein-and-version-control/](http://versioncontrolblog.com/2007/01/08/configurein-and-version-control/)的“*configure.in and versioncontrol*”。
- 前言
- 為什么寫這本書?
- 誰應該讀本書?
- 資料來源
- 致謝
- 免責聲明
- 1. 介紹
- 歷史
- 現狀
- 2. 起步
- 從你擁有的開始
- 選擇許可證并應用
- 設置風格
- 通告
- 3. 技術基礎設施
- 一個項目需要什么
- 郵件列表
- 版本控制
- Bug跟蹤
- IRC / 實時聊天系統
- RSS供稿
- Wikis
- 網站
- 4. 社會和政治的基礎架構
- 慈善獨裁者
- 共識為基礎的民主(Consensus-based Democracy)
- 寫下所有的內容
- 5. 金錢
- 參與的類型
- 長期雇傭
- 作為一些個體出現,而不是一個整體
- 公開你的動機
- 錢不能讓你可愛
- 契約
- 資助非編程活動
- 市場營銷
- 6. 交流
- 人如其文
- 避免常見的陷阱
- 刺兒頭
- 處理成長
- Bug跟蹤系統中無對話
- 公開性
- 7. 打包、發布和日常開發
- 版本號
- 發布分支
- 穩定發布版本
- 打包
- 測試和發布
- 維護多發布線
- 發布和日常開發
- 8. 管理志愿者
- 從志愿者中獲取最多
- 像分擔技術任務一樣分擔管理任務
- 轉化
- 提交者
- 榮譽
- 分叉
- 9. 許可證,版權和專利
- 術語
- 許可證的方面
- GPL和許可證兼容性
- 選擇一個許可證
- 版權分配和所有權
- 雙許可證模式
- 專利
- 深入資源
- A. 自由版本控制系統
- B. 自由Bug跟蹤系統
- C. 為什么我要關注車棚的顏色?
- D. 報告bug的樣例指導
- E. 版權