版本控制工具

2010 年 2 月 17 日

如果你花時間與軟體開發人員討論工具,我聽過最大的話題之一就是版本控制工具。一旦你開始使用版本控制工具,任何稱職的開發人員都會使用,它們就會成為你生活中很重要的一部分。版本工具不僅對維護專案歷程很重要,它們也是團隊協作的基礎。因此,我經常聽到有人抱怨版本控制工具很差,這並不令人意外。在我們最近的Thoughtworks 技術雷達中,我們提出了兩項企業應評估用於版本的控制工具:Subversion 和分散式版本控制系統 (DVCS)。在這裡,我想進一步說明這一點,總結我們在內部對版本控制工具進行的許多討論。

但首先要說明一些重點。我根據與 Thoughtworks 內部同事以及外部的各種朋友和夥伴的對話所收集的非科學資料撰寫了這篇文章。我沒有進行任何嚴格的測試或結構化的比較,因此與我大多數的寫作一樣,這篇文章是基於軼事證據。我近年來的個人經驗主要是 Subversion 和 Mercurial,但我的使用模式並非軟體開發團隊的典型模式。絕大多數我的聯絡人喜歡以敏捷 XP 的方式工作(即使許多人對此標籤嗤之以鼻),並且需要支援這種工作方式的工具。我預計很多人會對這篇文章感到不滿。我希望這種不滿會帶來好的文章,我可以連結到這些文章。

(在寫完這篇文章後,我確實做了一個小型VcsSurvey,這並沒有破壞我的結論。)

基本上有三個版本控制系統獲得廣泛認可:Subversion (svn)、GitMercurial (hg)。

低於推薦門檻

許多工具無法通過推薦門檻。原因有兩個:功能不佳或可見度不佳。

許多工具因缺乏功能而遭到 ThoughtWorkers 的一致抱怨。(ThoughtWorkers 是什麼,所有工具,包括首選的工具組,都會收到一些抱怨。那些低於門檻的工具會收到大部分的抱怨。)特別是兩個工具會產生很多批評:ClearCase(來自 IBM)和 TFS(來自 Microsoft)。他們會收到很多批評的原因之一是,他們在客戶端網站上非常受歡迎,而且公司政策通常強制使用它們(我將在最後說明應對策略)。

公平地說,這些問題通常會因公司使用 VCS 的政策而變得更複雜。我聽說一些團隊實施了非常奇怪的工作流程,這使得完成任何事情都成為一個持續的障礙。由於 VCS 是強制執行這些工作流程的工具,因此它確實會受到這種影響。

我不會在此詳細說明功能不佳的工具所遇到的問題,那將是另一篇文章。(這可能使我在 IBM 和 Microsoft 中變得更加不受歡迎。)我至少會暫時將它留給受我尊敬的開發人員,他們已廣泛使用這些產品,但不推薦這些產品。

將工具移到可推薦門檻後面的第二個原因是我沒有聽到許多關於某些工具的評論。這是一個問題,因為較不受歡迎的工具會讓人難以找到知道如何使用它們或想要找出它們的開發人員。有許多原因會讓原本不錯的工具落後於此。我曾經聽人說過 Perforce 的好話,但現在的感覺似乎是它沒有比 Subversion 更具吸引力的優勢,更不用說 DVCS 了。說到 DVCS,這裡我重點介紹的還有兩個以上的工具。特別是 Bazaar,是我偶爾會聽到好話的一個工具,但再次強調,我聽到的頻率遠低於 git 或 Mercurial。

在我完成那些低於門檻的工具之前,我只想對一個特別糟糕的工具說幾句話:Visual Source Safe,或我稱之為:Visual Source Shredder。感謝老天,我們現在較少看到它,但如果您正在使用它,我們強烈建議您放棄它。現在。它不僅使用起來很痛苦,我還聽過太多關於儲存庫損毀的故事,無法將比 foo.txt 更重要的東西託付給它。

因此,這留下三種我的聯絡人普遍滿意的工具。我發現這三種都是開源的,這很有趣。在這些工具之間進行選擇,首先涉及在集中式或分散式 VCS 模型之間進行選擇,然後,如果您選擇 DVCS,則在 git 和 mercurial 之間進行選擇。

分散式或集中式

大多數情況下,在集中式和分散式之間的選擇取決於開發團隊的技能和紀律性。分散式系統在工作流程中提供了很大的靈活性,但如果您沒有成熟度來很好地使用它,這種靈活性可能是危險的。Subversion 鼓勵使用一個簡單的中央儲存庫模型,不鼓勵大規模分支。在使用 持續整合 的環境中,這是我大多數朋友喜歡的工作方式,該模型非常合適。因此,Subversion 是大多數環境的理想選擇。

儘管 DVCS 在您安排工作流程的方式上提供了很大的靈活性,但我認識的大多數人仍然將其工作模式建立在與持續整合一起使用的共享主線儲存庫的概念上。儘管現代 VCS 幾乎擁有神奇的工具來合併不同人員的變更,但這些合併仍然只是合併文字。持續整合仍然是獲得語義一致性的必要條件。因此,即使是使用 DVCS 的團隊,通常仍然有中央主儲存庫的概念。

與其更酷的分散式表親相比,Subversion 有三個主要的缺點。

由於分散式系統始終為您提供整個儲存庫的本地磁碟副本,這表示儲存庫操作總是很快,因為它們不涉及對中央伺服器的網路呼叫。如果您正在查看記錄、對比舊版本,以及任何涉及整個儲存庫的操作,這是一個明顯的差異。如果這在我的家庭網路中很明顯,那麼如果您的儲存庫在另一個大陸,這將是一個大問題 - 就像我們在分散式專案中發現的那樣。

如果您離開與儲存庫的網路連線,分散式系統仍允許您使用儲存庫。您可以在飛機上提交工作的檢查點、瀏覽歷史記錄,以及在沒有網路連線的情況下比較版本。

最後一個缺點更像是一個社會問題,而不是真正的工具問題。DVCS 鼓勵快速分支以進行實驗。您可以在 Subversion 中進行分支,但它們對所有人可見這一事實會阻止人們為實驗工作開啟分支。類似地,DVCS 鼓勵工作檢查點:提交不完整的變更(甚至可能無法編譯或通過測試)到您的本地儲存庫。同樣,您可以在 Subversion 的開發人員分支上執行此操作,但這些分支位於共享空間這一事實會降低人們這樣做的可能性。

最後一點也導致了反對 DVCS 的論點,它鼓勵隨意分支,這在早期感覺很好,但很容易導致你合併失敗。特別是 FeatureBranch 方法是一種我不鼓勵的流行方法。與前面類似的評論一樣,我必須指出魯莽的分支並非特定於某個工具。我經常聽見在 ClearCase 環境中的人抱怨同樣的問題。但 DVCS 鼓勵分支,這就是我指出團隊需要更多技能才能很好地使用 DVCS 的主要原因。

有一種特殊情況,即使對於擅長使用 DVCS 的團隊,Subversion 也是更好的選擇。這種情況是,你協作處理的工件是二進位的,並且無法由 VCS 合併 - 例如 Word 文件或簡報檔。在這種情況下,你需要恢復到具有單一寫入者簽出的悲觀鎖定 - 而這需要一個集中式系統。

Git 或 Mercurial

所以如果你打算走 DVCS 路線 - 你應該選擇哪一個?Mercurial 和 git 獲得了大部分關注,所以我認為選擇在它們之間。然後,選擇歸結為功能與可用性,加上一點心智共享和 github 的陰影。

Git 肯定因其功能而受到喜愛。人們對它近乎神奇的自動正確合併文字的能力大為讚賞,即使面對檔案重新命名。我沒有看到任何比較合併功能的客觀測試,但主觀意見偏好 git。

(合併重命名,正如我的同事 Lucas Ward 定義的那樣,描述了以下場景。我將 Foo.cs 重新命名為 Bar.cs,Lucas 對 Foo.cs 進行了一些更改。當我們合併時,他的更改會正確應用到 Bar.cs。git 和 Mercurial 都可以處理這個。)

對於許多人來說,git 最大的缺點是它經常晦澀的命令和心智模型。Ben Butler-Cole 巧妙地表達了這一點:「有一個令人驚訝的強大事物在裡面扭動,它基本上可以做我可能要求它的任何事情,如果我知道怎麼做就好了。」對於它的批評者來說,git 缺乏可發現性 - 從其明顯的設計中逐漸推斷出它所做的事情的能力。Git 的支持者說,這在很大程度上是因為它使用與其他 VCS 不同的心智模型,所以你必須更多地忘記你對 VCS 的了解才能欣賞 git。無論出於何種原因,git 似乎更吸引那些喜歡學習內部結構的人,而 mercurial 似乎更吸引那些只想進行版本控制的人。

GitHub 的影子在此處很重要。即使是 git 懷疑論者也認為它是專案協作的絕佳場所。Mercurial 的等價服務 bitbucket,就是無法激起相同的喜愛。然而,還有其他網站可能開始縮小差距,特別是 Google Code 和 Microsoft 的 Codeplex。(我發現 Codeplex 使用 Mercurial 非常令人振奮。Microsoft 經常因與互補的開源產品合作不佳而受到批評,這是正確的。他們在其開源託管網站上使用 Mercurial 是個非常令人振奮的跡象。)

從歷史上來看,git 在 Windows 上的運作不佳,差到我們不建議使用。這現在已經改變,只要您使用 msysgit 而不是 cygwin 來執行它。我們現在的看法是 msysgit 足夠好,可以讓與 Mercurial 的比較對 Windows 來說不再是個問題。

人們普遍認為 git 比 Mercurial 更能處理分支,特別是針對實驗和檢查點的短期分支。Mercurial 鼓勵使用其他機制,例如快速複製單獨的儲存庫目錄和佇列修補程式,但 git 的分支是一個更簡單、更好的模型。

Mercurial 似乎對大型二進位檔案有問題。我的普遍建議是,這樣的東西通常最好使用 Subversion 來管理,但如果您有太少檔案無法保證單獨管理,那麼 Mercurial 可能會被您擁有的少數檔案掛起。

多個 VCS

同時使用多個 VCS 通常是有價值的。這通常是需要使用比您的團隊想要使用的 VCS 功能更少的 VCS 的地方。

我們經常遇到的情況是,公司標準採用有缺陷的 VCS(通常是 ClearCase),但我們希望有效率地工作。在這種情況下,我們成功地使用不同的 VCS 進行日常團隊團隊工作,並在必要時提交到公司 VCS。因此,雖然團隊 VCS 每人每天會看到幾次提交,但公司 VCS 每週或每兩週會看到一次提交。通常,這是公司管理員在任何情況下都偏好的。從歷史上看,我們使用 svn 作為本機 VCS 來執行此操作,但未來我們更有可能使用 DVCS 作為本機前端。

這種雙重使用情境在 git-svn 也很常見,人們在本地端使用 git,但提交到共用的 svn 系統。Git-svn 是另一個選擇 git 而非 mercurial 的原因。對遠端網站工作來說,使用本機 DVCS 特別有價值,因為網路中斷和頻寬問題可能會癱瘓遠離集中式 VCS 的網站。

許多團隊可以從這種雙重 VCS 工作方式中受益,特別是如果其公司 VCS 強制執行許多公司儀式。使用雙重 VCS 通常可以讓本地開發團隊和公司控制者更滿意,因為他們對 VCS 的動機通常不同。

最後一個備註

請記住,儘管我在這裡對工具喋喋不休,但通常是實務和工作流程會帶來更大的差異。工具當然可以讓使用一套良好的實務變得容易得多,但最終還是取決於人們為其環境使用有效的工作方式。我喜歡允許許多小變更快速整合使用持續整合的方法。我寧願使用具有 CI 的差勁工具,也不願使用沒有 CI 的好工具。