版本模型

版本控制系統的核心任務是實現協作編輯和資料共享,但是不同的系統使用不同的策略實現這個目的。我們有許多理由要去理解這些策略的區別,首先,如果你遇到了其他類似Subversion的系統,可以幫助你比較現有的版本控制系統。此外,可以幫助你更有效的使用Subversion,因為Subversion本身支持不同的工作方式。

文件共享的問題

所有的版本控制系統都需要解決這樣一個基礎問題:怎樣讓系統允許用戶共享訊息,而不會讓他們因意外而互相干擾?版本庫裡意外覆蓋別人的更改非常的容易。

考慮圖 1.2 「需要避免的問題」的情景,我們有兩個共同工作者,Harry和Sally,他們想同時編輯版本庫裡的同一個文件,如果首先Harry保存它的修改,過了一會,Sally可能湊巧用自己的版本覆蓋了這些文件,Harry的更改不會永遠消失(因為系統記錄了每次修改),但Harry所有的修改不會出現在Sally新版本的文件中,所以Harry的工作還是丟失了—至少是從最新的版本中丟失了—而且可能是意外的,這就是我們要明確避免的情況!

圖 1.2. 需要避免的問題

需要避免的問題

「鎖定-修改-解鎖」方案

許多版本控制系統使用鎖定-修改-解鎖機制解決這種問題,在這樣的模型裡,在一個時間段裡版本庫的一個文件只允許被一個人修改。首先在修改之前,Harry要「鎖定」住這個文件,鎖定很像是從圖書館借一本書,如果Harry鎖住這個文件,Sally不能做任何修改,如果Sally想請求得到一個鎖,版本庫會拒絕這個請求。在Harry結束編輯並且放開這個鎖之前,她只可以閱讀文件。Harry解鎖後,就要換班了,Sally得到自己的輪換位置,鎖定並且開始編輯這個文件。圖 1.3 「「鎖定-修改-解鎖」方案」描述了這樣的解決方案。

圖 1.3. 「鎖定-修改-解鎖」方案

「鎖定-修改-解鎖」方案

鎖定-修改-解鎖模型有一點問題就是限制太多,經常會成為用戶的障礙:

  • 鎖定可能導致管理問題。有時候Harry會鎖住文件然後忘了此事,這就是說Sally一直等待解鎖來編輯這些文件,她在這裡僵住了。然後Harry去旅行了,現在Sally只好去找管理員放開鎖,這種情況會導致不必要的耽擱和時間浪費。

  • 鎖定可能導致不必要的線性化開發。如果Harry編輯一個文件的開始,Sally想編輯同一個文件的結尾,這種修改不會衝突,設想修改可以正確的合併到一起,他們可以輕鬆的並行工作而沒有太多的壞處,沒有必要讓他們輪流工作。

  • 鎖定可能導致錯誤的安全狀態。假設Harry鎖定和編輯一個文件A,同時Sally鎖定並編輯文件B,如果A和B互相依賴,這種變化是必須同時作的,這樣A和B不能正確的工作了,鎖定機制對防止此類問題將無能為力—從而產生了一種處於安全狀態的假相。很容易想像Harry和Sally都以為自己鎖住了文件,而且從一個安全,孤立的情況開始工作,因而沒有盡早發現他們不匹配的修改。鎖定經常成為真正交流的替代品

「複製-修改-合併」方案

Subversion,CVS和一些版本控制系統使用複製-修改-合併模型,在這種模型裡,每一個客戶聯繫項目版本庫建立一個個人工作副本—版本庫中文件和目錄的本地映射。用戶並行工作,修改各自的工作副本,最終,各個私有的拷貝合併在一起,成為最終的版本,這種系統通常可以輔助合併操作,但是最終要靠人工去確定正誤。

這是一個例子,Harry和Sally為同一個項目各自建立了一個工作副本,工作是並行的,修改了同一個文件A,Sally首先保存修改到版本庫,當Harry想去提交修改的時候,版本庫提示文件A已經過期,換句話說,A在他上次更新之後已經更改了,所以當他通過客戶端請求合併版本庫和他的工作副本之後,碰巧Sally的修改和他的不衝突,所以一旦他把所有的異動清單(Changesets)成到一起,他可以將工作副本保存到版本庫,圖 1.4 「「複製-修改-合併」方案」圖 1.5 「「複製-修改-合併」方案(續)」展示了這一過程。

圖 1.4. 「複製-修改-合併」方案

「複製-修改-合併」方案

圖 1.5. 「複製-修改-合併」方案(續)

「複製-修改-合併」方案(續)

但是如果Sally和Harry的修改交迭了該怎麼辦?這種情況叫做衝突,這通常不是個大問題,當Harry告訴他的客戶端去合併版本庫的最新修改到自己的工作副本時,他的文件A就會處於衝突狀態:他可以看到一對衝突的異動清單(Changesets),並手工的選擇保留一組修改。需要注意的是軟體不能自動的解決衝突,只有人可以理解並作出智能的選擇,一旦Harry手工的解決了衝突—也許需要與Sally討論—它可以安全的把合併的文件保存到版本庫。

複製-修改-合併模型感覺有一點混亂,但在實踐中,通常運行的很平穩,用戶可以並行的工作,不必等待別人,當工作在同一個文件上時,也很少會有交迭發生,衝突並不頻繁,處理衝突的時間遠比等待解鎖花費的時間少。

最後,一切都要歸結到一條重要的因素:用戶交流。當用戶交流貧乏,語法和語義的衝突就會增加,沒有系統可以強制用戶完美的交流,沒有系統可以檢測語義上的衝突,所以沒有任何證據能夠承諾鎖定系統可以防止衝突,實踐中,鎖定除了約束了生產力,並沒有做什麼事。