5.日常操作
在具有版本管理的小組開發環境中,有些操作是開發人員幾乎每天都要進行的,如提交修 改工作、更新本地工作拷貝、解決沖突等。下面將詳細介紹在ECLIPSE 中如何實現這些日常 操作。在進行這些操作前,都需要先建立與CVS服務器的連接。在ECLIPSE中進行這些操作時 ,如果是對目錄進行操作,則 ECLIPSE會自動對該目錄下的子目錄和文件進行相同的操作, 對目錄的操作是遞歸嵌套的。本文在下面的講解中只以文件操作為例,但這些操作也適用於 目錄。一般來說,如果在某個目錄下要對多個文件進行相同的操作,則選擇目錄操作比較簡 便。另外,如不特別說明,CVS資源庫中的文件指的是屬於主分支 HEAD的文件。
5.1 提交(commit)
下面分四種不同的工作場景介紹如何將對工作拷貝的修改反映到CVS資源庫。
a.簽出模塊後,在本地(Local)對文件進行了修改,CVS資源庫中的文件沒有變化。
在工作拷貝中對SimpleTest.java作一些改動並保存,此時ECLIPSE的畫面見圖17。在改動 的文件及其所屬的目錄前都出現一個箭頭,在希望提交的文件上點擊右鍵,在出現的彈出菜 單中選擇【Team】→【Commit...】,在隨後出現的對話框中輸入注釋後單擊OK按鈕。雖然注 釋不是必須輸入的,但是,最好養成在每次提交時寫注釋的良好習慣,這在實際的系統開發 過程中是很有必要的。提交成功後文件的修訂版本號會自動增加,如圖18所示, SimpleTest.java的修訂版號從1.1變成了1.2。
圖17:在ECLIPSE中能明確地標識被修改過的工作拷貝
圖18:提交修改後,修訂版號自動增加
b.簽出模塊後,在項目中新建了新文件,希望將新建的文件追加到CVS資源庫中。
在新建的文件上點擊右鍵,在出現的彈出菜單中選擇【Team】→【Add to Version Control】。需要注意的是:上述操作並沒有把新建的文件追加到CVS資源庫中,為了把新建 的文件追加到CVS資源庫中,還要執行下列操作:在新建的文件上點擊右鍵,在出現的彈出菜 單中選擇【Team】→【Commit...】。
c.簽出模塊後,在項目中刪除了文件,希望在CVS資源庫中也刪除相應的文件。
首先在項目中刪除文件,然後在被刪除文件的父目錄上點擊右鍵,在出現的彈出菜單中選 擇【Team】→【Commit...】。值得指出的是:上述操作只是將被刪除的文件從主分支上刪除 了,但並沒有從CVS資源庫中被完全刪除,也不應該從CVS資源庫中被完全刪除,因為某個標 簽或分支可能需要被刪除的文件。
如果想恢復被刪除的文件,在ECLIPSE的Navigator視圖中選中被刪除的文件的父目錄,在 右鍵菜單中選擇【Team】→【Restore from Repository...】,然後在出現的對話框中選擇 希望從哪個修訂版恢復被刪除文件的內容。
d.簽出模塊後,在本地(Local)對文件進行了修改,但在提交之前,其他的開發人員已 經對同一個文件進行了修改並提交到CVS資源庫中。
此時,由於CVS資源庫中該文件的修訂版本號將高於本地該文件的修訂版本號,因此將不 能提交該文件。如果試圖提交該文件,ECLIPSE將彈出一個錯誤對話框,見圖19。在這種情況 下,為了能提交修改必須首先解決沖突。詳細操作見下文的沖突解決。
圖19:在沖突狀態下提交將出現錯誤
在小組開發環境中,應該經常性地提交自己的工作成果,但也不能隨意提交。一般來說, 以提交的更改不對其他開發人員造成妨礙為前提條件。例如,提交的代碼應能夠被正常編譯 。如果在小組開發環境中還使用了諸如CHECKSTYLE之類的代碼審查工具,則提交的代碼除了 能夠被正常編譯之外,還應能通過代碼審查工具的審查。
5.2 更新(Update)
在系統的開發過程中,開發人員不應只關注自己的開發,還應盡量與其他開發人員保持同 步,也就是需要經常地將其他開發人員的開發成果更新到本地的工作拷貝中。
a. CVS資源庫中的文件被更新了,但本地文件沒有更新。
在開發小組中,可能有部分開發人員負責一些通用模塊的開發,而其余的開發人員則專注 於業務系統的開發。在這樣的開發場景中,業務系統的開發人員就應經常更新通用模塊,保 持工作拷貝中的通用模塊與CVS資源庫中通用模塊的同步。在文件上點擊右鍵,在出現的彈出 菜單中選擇【Team】→【Update...】。本地文件的內容將被替換為CVS資源庫中相應文件的 內容。
b. CVS資源庫中的文件沒有被更新,但本地文件被更新了。
此時,由於本地文件的修訂版號與CVS資源庫中文件的修訂版號相同,更新操作實際上什 麼也不做。
c. CVS資源庫中的文件和本地文件都被更新了。
此時,ECLIPSE會盡量將CVS資源庫中的內容合並到本地文件中。如果在合並過程中沒有發 現沖突,則合並後的文件將包含本地修改和其他開發人員的修改;如果在合並過程中產生了 沖突,則ECLIPSE會在合並文件中著重顯示相沖突的部分,並將原本地文件作一個備份。圖 20~23演示了這一過程。 cvstest.txt文件1.2版本的三行的內容分別為test line1、test line2、test line3。用戶jiangch將文件內容修改並保存後的結構如圖20,在jiangch提交之 前,用戶cvsuser2已將文件內容修改並提交,此時 CVS資源庫中cvstest.txt的修訂版號為 1.3,見圖21。
圖20:存在沖突的更新1--用戶jiangch的修改結果
圖21:存在沖突的更新2--用戶cvsuser2修改並提交後的結果
用戶jiangch在文件cvstest.txt上進行更新操作後的結果見圖22。
圖22:存在沖突的更新3--用戶jiangch進行更新操作後的結果
第二行保持不變,但產生沖突的第一、三行則被標記出來了。cvstest.txt的修訂版號也 變為1.3並處於已修改狀態,新產生的文件.#cvstest.txt.1.2是修訂版號1.2的備份文件。通 過手工將jiangch與cvsuser2的修改內容合並後就可以進行提交操作了,圖23是一個合並後提 交的結果。
圖23:存在沖突的更新4--用戶jiangch合並後提交
5.3 沖突解決
ECLIPSE 為CVS的操作提供了一個非常實用的功能:同步透視圖(Team Synchronizing Perspective)。通過同步透視圖,我們可以在提交、更新操作之前就發現可能存在的沖突。 使用ECLIPSE小組開發環境的開發人員都應該熟悉同步透視圖的使用。圖21~24演示了如何使 用同步透視圖。在cvstest.txt 1.6與cvstest2.txt1.13的基礎上用戶jiangch對這兩個文件 進行了修改並保存。此時的結果如圖24。
圖24:沖突解決1--用戶jiangch的修改結果
用戶cvsuser2也在cvstest.txt 1.6、cvstest2.txt 1.13、TextRunnerTest.java1.1的基 礎上對這三個文件進行了修改並將修改結果提交到了CVS資源庫。其結果見圖25。
圖25:沖突解決2--用戶cvsuser2修改並提交後的結果
如果用戶jiangch不能確定只有他一個人會修改這兩個文件,他可以在如圖21的畫面上選 擇這兩個文件並點擊右鍵,在出現的彈出菜單中選擇【Team】→ 【Synchronize with Repository...】,出現如圖26所示的畫面。圖中①②③④所標識的按鈕是過濾器,分別對應4 種模式,可以控制在同步視圖中顯示何種狀態的文件。
①:Incoming模式,顯示CVS資源庫中修訂版號高於工作拷貝的文件。在實際工作中,可以 選中此類文件並在右鍵菜單中選擇【Update】。也就是將其它開發人員的開 發成果反映到自 己的工作拷貝中,保持與其它開發人員的同步。
②:Outgoing模式,顯示工作拷貝作了修改的文件。在實際工作中,可以選中此類文件並在 右鍵菜單中選擇【Commit】。也就是將自己的開發成果反映到CVS資源庫。
③:雙向模式,顯示所有不同步的文件。包含模式①、模式②、模式④。
④:沖突模式,只顯示在本地拷貝與CVS資源庫都修改過且產生了沖突的文件。模式①-模 式③包含了沖突模式。
圖26:沖突解決3--同步透視圖
處於沖突狀態下的文件是不能提交的,為了提交產生沖突的文件,首先必須解決沖突。雙 擊產生了沖突的文件,可以在一個特殊的對比編輯器中同時顯示本地的工作拷貝文件與CVS資 源庫中的文件。通過這個編輯器可以方便地看到哪些地方存在沖突並解決沖突。例如在圖26 中,假定希望將工作拷貝的第一行和CVS資源庫的第三行作為最終的修改結果,可以從編輯器 的第二列拷貝第三行到第一列的第三行並保存。在同步視圖中提交修改的操作:
1.在希望提交的文件上點擊右鍵,在出現的彈出菜單中選擇【Team】→【Mark As Merged 】,這將使文件從沖突模式變為Outgoing模式。
2.在文件的右鍵菜單中選擇【Team】→【Commit】。圖27是提交後的結果畫面。同步透視 圖還包含了很多其它的實用功能,關於同步透視圖中各種按鈕與右鍵菜單的說明可以查閱 ECLIPSE的聯機幫助文檔。
圖27:沖突解決4--用戶jiangch合並後提交
5.4 比較、替換、修改履歷
在軟件項目的開發進程中,可能需要參考歷史版本的信息,甚至將某個文件的內容回復到 某個歷史修訂版。在ECLIPSE中也提供了這方面的功能。文件或目錄的右鍵菜單【Compare With】提供了和其它修訂版相比較的功能;右鍵菜單【Replace With】提供了將工作拷貝的 內容替換為其它修訂版內容的功能。例如,我們修改了工作拷貝的某個文件後又想放棄修改 內容,此時,可以選中文件並在右鍵菜單中選擇【Replace With】→【Last from Head】( 假定CVS資源庫沒有被其他人員更新過,否則【Replace With】→【Revision...】)。上述 操作對目錄而言,實際上是對該目錄中的所有文件執行操作。
在 ECLIPSE中,通過文件的右鍵菜單【Team】→【Show Resource History】可以方便地 查詢文件的修改履歷,例如文件cvstest.txt在某個時刻查詢到的修改履歷見圖28。從中可以 看出誰在什麼時候修改了文件的內容,也可以看出在每次提交時都寫注釋會有助於追蹤代碼 的修改意圖及今後的代碼維護工作。
圖28:文件修改履歷
6.標簽與分支
6.1 標簽
考慮下面的應用場景:在項目基本完成的時候,我們希望為此時的文件狀態(快照)建立 一個標簽milestone1。在後續的程序修改過程中,如果發現了一些在版本milestone1中不存 在的BUG,我們就可以用milestone1這一統一的標識獲取當時的文件快照並與修改後的文件進 行對比,而不需要對每個文件都記住其修訂版號。
在ECLIPSE中,有兩種方法給模塊建立標簽。方法1.在工作拷貝上建立標簽, 就JAVA項目 而言,可以通過JAVA透視圖的右鍵菜單進行操作;方法2. 在CVS資源庫視圖中建立標簽。在建 立標簽之前,最好保持工作拷貝與資源庫的同步。以方法2為例,在CVS資源庫視圖的HEAD節 點下選中希望建立標簽的模塊,在出現的右鍵菜單中選擇【Tag as Version...】,在隨後出 現的對話框中添加標簽名即可。圖29是對模塊UnitTest建立了milestone1和milestone2兩個 標簽後的結果。
圖29:建立了兩個標簽後的CVS資源庫視圖
標簽與文件修訂版號的關系見圖30。某個標簽內各個文件的修訂版號可能不同,例如在標 簽1中,文件A的修訂版號是1.2,而文件B的修訂版號是1.3;同一個文件的相同修訂版號也可 能分屬於不同的標簽,例如在標簽1和標簽2中,文件B的修訂版號都是1.3。
圖30:標簽示意圖
從標簽簽出的模塊是靜態的,即使修改了本地的拷貝文件也不能向資源庫提交。為了證實 這一點,讀者可以先簽出Versions節點下的模塊,在本地做修改後再向CVS資源庫提交修改。 此時將出現類似圖31的錯誤提示畫面。表明提交的文件屬於標簽milestone1,而milestone1 不是分支因而不能提交。
圖31:從標簽簽出的拷貝修改後也不能被提交
6.2 分支
6.2.1 建立分支
雖然通過標簽可以方便地管理多個文件的修訂版號,但是通過標簽獲得的文件拷貝是靜態 的,無法在其基礎上修改並提交。因此,也就不能支持下面場景中的並發開發。假設某軟件 公司經過一段時間的開發,發布了產品A的1.0版。為了進一步擴大該產品的市場份額,隨即 在1.0版本的基礎上進一步研發功能更強大的 2.0版。但是公司還必須對產品1.0版進行維護 和支持,如果用戶在1.0版的使用過程中發現了BUG,應能盡快推出1.0修正版並發布相應的補 丁程序。也就是說,開發人員要能在1.0修正版與2.0版這兩條開發路線上同時工作。建立分 支則可以支持上述要求。
與建立標簽類似,在ECLIPSE中建立分支也有兩種方法。本文以在CVS資源庫視圖中的操作 為例演示分支的建立過程,其步驟如下:
1. 按建立標簽的方法建立一個新的標簽,例如v1_0。
2. 選中新標簽v1_0,在右鍵菜單中選擇【Add to Branch List...】(不限於新標簽v1_0 ,可以在任意標簽上操作,但是建立分支應當在關鍵時刻進行)。
3. 在出現的對話框中輸入分支名,例如輸入"UnitText1_0_X"並確定,此時就建立了分 支。但是,此時的分支是空的,沒有與之相關聯的資源。
4.選中新標簽v1_0,在右鍵菜單中選擇【Tag with Existing...】,在出現的對話框中 打開節點Branches並選擇在步驟3新建立的分支UnitText1_0_X,最後按OK按鈕確定後就完全 建立了一個新的分支,分支建好後的CVS資源庫視圖如圖32所示。
圖32:建立分支後的CVS資源庫視圖
現在,就可以從主分支和UnitText1_0_X分支分別獲得工作拷貝。從主分支獲得的工作拷 貝在提交後將反映到主分支上,而從 UnitText1_0_X分支上獲得的工作拷貝在提交後將反映 到UnitText1_0_X分支中,在主分支和UnitText1_0_X分支上可以互不影響地進行並發開發。 結合上述開發場景,產品A 1.0版的修正版對應UnitTest1_0_X分支,而產品A 2.0版可以在主 分支上繼續開發。
6. 2.2 分支修訂版號
分支中的修訂版號與主分支中的修訂版號略有不同,主分支、分支及修訂版號的關系可用 圖33來說明。
圖33:主分支與分支示意圖
圖 34顯示了文件cvstest.txt在UnitTest1_0_X分支上第一次提交後修訂版號的變化情況 。其修訂版號不是從"1.10"轉變為"1.11",而是轉變為"1.10.2.1"。如果對該文件再進行一 次提交,其修訂版號將轉變為"1.10.2.2"。即變化的是最後一個小數點後的數字。
圖34:分支修訂版號變化
6.2.3 將分支上的修改合並到主分支
繼續2.1中的場景,開發人員在開發產品A 2.0版的同時還對1.0版進行維護。開發人員根 據產品A 1.0版用戶的反饋修正了一些BUG,由於產品A 2.0版也是基於1.0版繼續開發的,他 們發現有些BUG在開發中的2.0版中也存在。此時,就希望能將1.0修正版中的修改合並到主分 支中。
圖35-39演示了分支合並的過程。建立UnitTest1_0_X分支後繼續在主分支上修改並提交 cvstest.txt,結果如圖35所示。
圖35:分支合並1--主分支中的文件內容
從 UnitTest1_0_X分支簽出一個項目(如果用戶jiangch或cvsuser2使用現有的ECLIPSE, 則在簽出項目時需要選擇【Check Out As...】菜單並給項目取一個不同於"UnitTest"的名字 ),對文件cvstest.txt進行修改並提交,結果如圖36所示。從圖36還可以看出,從分支簽出 的項目在項目名稱的後面還會注明分支的名稱。
圖36:分支合並2--UnitTest1_0_X分支中的文件內容
選擇主分支工作拷貝的cvstest.txt,在其右鍵菜單中選擇【Team】→【Merge...】,出 現如圖37所示的對話框。在"希望被合並的分支或標簽"輸入框中輸入"UnitTest1_0_X";在隨 後的"通用基版本" 輸入框中輸入"v1_0",其意義為分支的起源版本(參見本文建立分支的步 驟3和步驟4)。
圖37:分支合並3--選擇希望被合並的分支及其起始標簽
在圖37中點擊"Finish"按鈕,將出現同步透視圖。如果希望將分支中文件內容的第二行合 並到主分支中,只需將其從對比編輯器第二列拷貝至第一列,然後在文件的右鍵菜單中選擇 【Mark as Merged】(見圖38),最後在文件的右鍵菜單中選擇【Commit】。
圖38:分支合並4--在透視圖中進行合並操作
合並後的結果見圖39。
圖39:分支合並5--合並後主分支的結果
7.結束語
本文通過實例講述了如何在ECLIPSE中使用CVS進行版本管理,由於ECLIPSE內置了豐富的 CVS功能,本文的內容不可能面面俱到,例如,本文沒有涉及在ECLIPSE中修改CVS的相關設置 。想進一步了解相關內容的讀者可以參考聯機幫助文檔及文後的參考資料。另外,限於水平 ,文中如有不當之處,敬請批評指正。