經驗分享|大型分布式團隊的代碼版本管理
不管團隊最終選用什么代碼版本管理工具,只要適合自己的團隊的開發流程和工作方式,并且代碼管理順暢就可以了。
介紹這個話題,有兩個原因:
- 從開始工作到現在,我經歷過沒有代碼版本管理、代碼集中式管理,以及現在的分布式管理,我深刻體會到它在軟件開發過程中的重要性;
- 我在工作中遇到的很多客戶都存在對于代碼版本管理的各種問題、困惑和不同的需求。
所以,我希望將我在這個方面的經驗分享給更多人,希望能幫助更多的團隊解決在代碼版本控制方面的問題和疑惑。
一、代碼版本管理系統的歷史
代碼版本管理系統大致可以分為三個時代:
第一代:本地式
這代主要的特點提供本地代碼版本控制,比如SCCS(1972)、 PVCS(1985)等。
這代主要實現了基本的代碼版本管理,但缺點是無法讓多人同時對一個版本庫進行修改。這個也和當時軟件規模不夠大有關,也沒有這樣的需求。
第二代:客戶端-服務器式
這代主要的特點是提供集中式服務器端代碼版本控制,比如 CVS(1986), ClearCase(1992), Visual SourceSafe(1994), Perforce(1995), Subversion(2000) 等。
這代主要是實現了中心服務器端的代碼版本管理,特點是可以讓多人同時對一個代碼版本庫進行同步和修改,但缺點也相當明顯:
- 在無法連接服務器的情況下,無法查看日志以及提交和比較代碼版本(慢速網絡和遠程異地工作的程序員的痛),以及當服務或者網絡出現問題的時候很多人員就會無法工作。
- 不支持local branch,導致branch創建管理復雜,并且一旦創建就很難修改(快速迭代開發中的程序員的痛)
- 由于只有一個中心端服務器,一旦發生災難性問題,那么所有日志都會丟失,所以需要經常做備份(備份需要不小的成本)
- 如果軟件代碼量過于龐大,一般會出現速度緩慢的情況,因為每次的日志查詢、不同版本之間的代碼比較和代碼提交等操作都需要和服務器通信,造成服務器端的負載過大。
第三代:分布式
這代主要的特點是提供分布式代碼版本控制,比如Git(2005), Mercurial(2005)等。
這代結合了第一代和第二代的優點并實現了分布式的代碼版本管理。
這代的優點:分布式管理,在沒有和服務器有連接的情況下仍然可以查看日志,提交代碼,創建分支;支持local branch,可以快速方便的實現各種分支管理;支持分布式,從而可以實現分塊管理,以及負載分流管理。
缺點是有一定的學習曲線,比如分布方式下的代碼同步,local branch的理解與運用,分布式代碼管理的理解與運用等。詳細的比較可以參考:這里。
二、大型分布式團隊
曾經有這樣一個分布式團隊,他們在多個城市都有小分隊,并且正在開發一個大型項目,見下圖:
他們使用的代碼版本管理工具是第二代代碼管理工具SVN,管理方案如下:
但是他們在使用的過程中卻遇到了下面這些問題與痛點。
由于是分布式團隊,所以:
- 基于團隊的代碼模塊分離困難
當服務器不可用時:
- 不能查看提交記錄
- 不能比較文件
- 不能提交代碼
創建代碼分支時:
- 分支創建速度慢
- 多分支管理困難
在提交代碼時:
- 希望有Code Review
- 希望有CI Review
因為代碼龐大:
- 查看日志慢
備份代碼庫的時候:
- 需要停機備份
- 備份成本高
針對以上問題,可以使用新一代的分布式的代碼版本管理系統來解決,見下圖:
其中每一個團隊都有自己獨立的代碼庫,有一個中心庫用于同步這些獨立的代碼庫,并且每個庫都由團隊自己管理和維護。而且代碼版本管理系統需要支持輕量分支,代碼評審,離線提交,離線查看日志等功能。
但是由于當前沒有一個單一的代碼版本管理工具能同時滿足以上所有需求,所以很多公司都基于它們開發集成管理系統,比如Gerrit,GitLab,GitHub,BitBucket等。其中的Gerrit由于其開源,免費,以及由Google開發和維護,并管理著Android,OpenStack等大型項目源代碼的特點,成為了大型分布式團隊優先選擇的系統。
三、Gerrit
Gerrit是由Google開發的,用于管理Google Android項目源代碼的一個系統。它是基于Java和Prolog等開發的,支持Git,權限管理,代碼評審等綜合的一個管理系統。它與GitLab和GitHub最大的不同是它隱藏了代碼分庫管理的細節,使得開發人員不需要進行fork這樣的手工分庫和同步操作就可以進行代碼開發和提交,節省了開發人員的時間,見下圖:
由于Android本身是一個開源項目,所以貢獻者非常多,開發團隊也遍布多個地方(存在時差),導致“如何保證代碼質量”成為一個很大的問題。為此Google在Gerrit中加入了功能強大并且十分嚴格的代碼評審系統。
首先當代碼提交以后并不會直接merge到中心庫里面,它會暫時存在一個臨時庫里面,同時生成一個代碼評審記錄,并向特定的評審人員發送請求評審的郵件。當評審者在評審代碼之后,如果通過就需要在Gerrit系統里面對代碼進行打分,如果通過了就可以將代碼merge到中心庫里面去,如果沒有通過,那么這個代碼提交就需要被返還給開發者進行修改。
與此同時它還可以自動觸發一次包含本次代碼提交的CI構建(前提需要手工預先配置),如果CI自動構建和測試通過,也可以自動在Gerrit系統里面進行打分,可以給最終進行merge的人員進行參考。示意流程見下圖:
由于Android源代碼由上百個獨立的代碼庫組成,并且編譯一個Android系統需要大部分代碼庫里面的代碼,所以如何管理如此多的代碼庫也是一個難題,比如如何一次性同步需要編譯一個需要支持特定設備的代碼庫組合。為此Google基于Python語言開發一個工具叫Repo ,這個工具可以自定義你需要的代碼庫的組合,并且一次性對這些代碼庫進行同步,比如pull和push,見下圖:
四、SVN到Git的遷移
對于想從集中式代碼管理系統遷移到分布式代碼管理系統的團隊來講,如果團隊規模小,那么問題一般都不大,但是對于大型分布式團隊卻是困難重重。最主要的兩個困難:
- 代碼量太大,很難一次性將所有的代碼和日志等在短時間內遷移成功。
- 由于下屬團隊太多,很難同一時間讓所有團隊都切換至新的代碼管理工具。
為了解決這些難題,一般都會首先選用1個團隊來使用新的代碼版本管理工具。如果這個團隊轉換成功,再將其作為標桿向其他團隊推廣,從而逐步的將所有團隊切換到新的工具上去。
SVN到Git的遷移方案一般主要會使用兩種工具:
- 開源免費的git-svn;
- 商業收費的Subgit。
其中使用Subgit的遷移方案,如下圖:
如果團隊組資源充足,還可以使用Gerrit搭建一個獨立的Git服務器,從而以分布式的方式進行代碼遷移,如下圖:
五、多產品線的管理
使用同一個中心代碼庫管理多產品線一直是大型項目的一個困難點,特別是使用SVN這樣的工具更是難以管理,因為SVN這種工具的Branch本質上是一個目錄拷貝,并且速度慢,而且代碼回遷也需要手動進行。但是如果使用Git的特性來管理多產品線,比起SVN是事半功倍。具體方案見下圖:
總結
分布式代碼版本管理系統并不一定適合所有團隊,比如中小團隊可能更關心的只是成本更低,簡單易用,那么SVN等這類集中式版本管理工具還是更為適合。但是,不管團隊最終選用什么代碼版本管理工具,只要適合自己的團隊的開發流程和工作方式,并且代碼管理順暢就可以了。
作者:劉冉,現任 ThoughtWorks 資深軟件質量咨詢師,超過13年軟件開發和測試工作經驗。最熟悉的領域是嵌入式系統開發、Linux系統開發、各種腳本、測試工具、自動化測試系統開發、以及Agile中的QA。
本文由 @ThoughtWorks (微信公眾號:“思特沃克”) 原創發布于人人都是產品經理。未經許可,禁止轉載。
早上的好文!棒!