Posted on 2010-09-03 16:22
幻海藍夢 閱讀(366)
評論(0) 編輯 收藏 所屬分類:
版本管理
我參與的項目release好一段時間了,這期間經歷了市場血與火的洗禮...。做應用軟件的就是這樣,你一定會碰到不同用戶的不同需求,你需要為其定制開發。好,當有A省的用戶有特殊的需求的時候,我們就用CVS為其建立一個新的project。同理,當有B省用戶有特殊的需求的時候,我們還是采用同樣的辦法。我們一開始沒有覺得這樣哪里不好,為不同的用戶建立不同的project,很清晰,維護起來還挺方便。就像《后天》里的情節哪樣,你總是要對你不正確的做法付出慘痛的代價。我們很快發現了我們的做法的致命傷,當我們需要修改一個bug,或者是升級程序,加入通用的功能的時候,我們需要手工同步很多版本。god,大量的重復勞動!我清楚的聽到我鄰座那個可愛的女孩的抱怨:真麻煩,要同步這么多版本。
有的時候,我覺得自己很幸運^_^。當有一個問題困擾著我的時候,我準備上一個常去的論壇向guru請教的時候,發現大家正在那里熱火朝天的討論著這個問題。這次也差不多,一天晚上和一個以前的同事聊了一些關于版本管理的問題。那個同事現在在一家外企工作,據稱他們的版本管理很規范,有很專業的專門人員來做這件事情。他告訴我,應該可以采用CVS的分支功能來解決這個問題。雖然我當時云里霧里,不太明白,他也不是做版本管理的,但是,重要的是這個idea。我是一個聽人勸的人,馬上從一個同事那里揩來《CVS-開源軟件開發技術》那本書。仔細的研究了一下分支的功能。嘖嘖,這就是我想要的,哈哈,在屋里跳了一會小天鵝。嗯,程序員總是這樣大喜大悲的!
把我的輕騎兵音箱調到很大聲,聽著《癡心絕對》。我喜歡這樣寫文章^_^。好吧,讓我們看看什么是CVS的分支。
我們把一個項目的一個主要開發過程稱作開發主線。當某一個特殊事件發生的時候,例如,有一個用戶有特殊的需求,于是就從這個開發主線里分離出來一個叉,以滿足用戶特殊的需求,那么這個叉有它自己的發展方向,這就是分支,就像是一個大樹在春暖花開的時候,長出來的新枝。
---------分支
/
/
/
------●----------------------------開發主線
上面這個點,代表開發主線的最新版本,那么這個時候可以從開發主線建立分支來進行定制開發。接下來,開發主線和分支就可以有各種的發展方向。而且,如果可以的話,分支的代碼可以重新合并到開發主線中。開發主線的代碼也可以更新到分支代碼中。
假設在我們的home目錄下的proj目錄就是我們的工程。下面具體看一下,如何建立分支:
1、先在開發主線上創建一個標簽,就是上圖中那個點。這樣做是為了以后可能有使主干重新回到分支創建時的狀態的需求。在你的工程目錄的top level下執行cvs tag Root-of-Version_2.5.0.0。
2、創建分支:cvs tag -b ln_version_branch(-b選項就是創建分支)。
3、接下來,你可以在工程目錄的top level下直接執行cvs update -r ln_version_branch轉到分支上進行工作。也可以通過cvs co -r ln_version_branch -d ln_proj proj命令新checkout一份分支的本地拷貝。-d選項是創建本地目錄名字。這里建議用第二種用法,因為在一個本地拷貝下通過命令來回在主線和分支轉換,容易產生混淆,你也可能忘記這么去做。
4、這樣分支的開發和主線的開發就可以分離開。如果需要的話,可以把分支上的代碼合并到開發主線上,當然在合并的過程中可能需要解決一些沖突。cvs update -j ln_version_branch,通過這樣的命令把分支代碼合并到主線上。當然我們這里的例子是針對用戶特殊需求產生的分支,一般不會把分支合并到開發主線中。但是,對于bug修改等產生的分支,就會有需求把分支合并到主線上。這里有一點要強調的是,當開發主線的程序員合并分支的代碼的時候,需要互相溝通。在開發主線程序員成功合并分支代碼后,在主線代碼上要設立一個點(cvs tag)來標志這次合并;在分支代碼上開發的程序員,在合并之后,也要建立一個點來標志這次合并,例如,cvs tag ln_version_1。這樣做的好處是當下次在進行代碼合并的時候,在開發主線上的程序員可以通過命令cvs update -j ln_version_1 -j ln_version_branch,這里ln_version_branch代表分支的末梢,因此該命令不是重新合并整個分支代碼,而是合并自從合并點ln_version_1到現在修改的代碼,這樣可以防止重新合并整個分支而帶來的沖突。
5、對于我們這里針對用戶特殊需求產生的分支,可能更多需要的是把開發主線上的代碼更新到分支上。cvs update -j HEAD,這里HEAD代表了主干的末梢,也就是這個命令合并了主線在創建該分支伊始到目前為止,所有的主線上修改的代碼。這里還是需要分支開發人員和主線開發人員溝通。在分支上也需要設立一個點來標志這次合并,這樣如果主線需要合并分支代碼的時候,可以根據這個點進行新的合并,而不是合并整個分支。主線開發人員也需要設置點來標志這次合并,例如,cvs tage merged-ln_version_1 ,這樣下次分支在合并主線代碼的時候可以cvs update -j merged-ln_version_1 -j HEAD ,這樣防止了分支重復合并主線上的代碼,而只是合并最新的修改。
上面我們可以看到,一個主要規則是,當進行代碼合并的時候,一定要注意溝通,合理的設置合并點。并且,合并點的名字也應該望文生義^_^。各個線上的合并工作也最好由一個人來做。如果合并點設置不當,那么分支帶來的好處可能就會打折扣。并且如果管理的不好,整個項目可能會很亂,產生意大利面條式的分支^_^。
CVS的工作模式:
CVS的基本工作模式如下:
CVS服務器(代碼文檔庫) / | \ (版 本 同 步) / | \ 開發者1 開發者2 開發者3
CVS在服務器端維護代碼文檔庫,不同的開發者在本地機器上建立對應代碼樹,并利用CVS保持本地代碼文檔同代碼文檔庫的一致。當由于多個開發者對文件的同時修改造成本地與庫中的代碼文件沖突時,CVS報告并協助解決沖突代碼的合并問題。普通開發者(非管理員)對CVS的使用流程如下所示:
Check out(獲取) -------------------- Merge(合并) | | ^ v v Conflict(沖突) | Modify(修改)-> Update(更新) ---------------- ^ | | | No Conflict(無沖突) | v Update(更新) <- Commit(提交) | v Export(導出)
check out命令只需在開始建立本地代碼樹時使用一次,其后更新本地代碼則使用update命令。update命令比較服務器和本地代碼庫的區別,并把本地代碼樹中過時的文件自動更新。當完成對代碼的修改之后,在提交代碼之前同樣需要使用update命令,以獲取他人并行修改的的代碼。如果出現沖突(即對同一文件同時進行了修改),CVS將在本地代碼中把兩者都保留并標記出來,要求開發者處理沖突。在沖突不存在或已解決的情況下,使用commit命令將服務器代碼更新為本地代碼。CVS要求為更改提供注釋,并自動為更新的文件處理版本編號。當軟件需要正式發布時,使用export命令導出不包含CVS設置信息的源代碼樹。
CVS的管理員還使用包括init, import, admin等命令對服務器和代碼庫進行配置和設置。
http://www.uml.org.cn/pzgl/200709149.asp