使用 TortoiseSVN 處理版本的分支與合併(一)

在介紹 Subversion 分支與合併的觀念時,常見以 trunk 代表主線版本、以 branch 代表支線版本的方式來組織檔案庫的目錄結構。例如,資料夾 MyProject\trunk 底下用來存放專案的主線版本,而 MyProject\branches 底下則存放支線的版本。

主線只一條,支線可能很多,當然,這些路線可以「分進合擊」。這篇講分(分支),下一篇講合(合併)。

一個例子

有時候,我們可能不會一開始就建立 trunk 目錄--也許是因為在建立檔案庫時,覺得專案沒那麼複雜,不需要這麼做;也可能是因為其他特殊原因,例如:團隊制定的規範。這裡用一個 ASP.NET Web 專案為例,說明可能碰到的問題與應變方法。

假設這個 ASP.NET Web 專案的目錄結構類似這樣:


這裡我們把文件、網站應用程式的原始碼、商業邏輯層的類別庫原始碼都加入檔案庫,並分別放在 Document、Web、和 BusinessLogicLib 資料夾底下。其中 Web 資料夾除了固定的 Bin 目錄,還依子系統分出庫存(Inventory)、會計(Account)、人事(HR)等子目錄。

現在假設碰到一種狀況:人事系統的使用者不斷提出新需求,導致該系統的程式需要大改。問題是,這些修改需要好幾月的時間才能完成,期間勢必還有一些更要緊的 bug 修正或細部的程式修改必須同時進行,怎麼辦?

一個直覺的辦法,是讓開發人員自行管理兩個版本,也就是說,把整個 HR 資料夾複製成另一份,目錄名稱也許叫做「HR_NewFeature」,代表這是為了開發新功能而特別建立的目錄。如此一來,開發人員就可以分頭修改 HR 和 HR_NewFeature 底下的檔案,等到需要交付時,才把兩邊的程式碼整合起來。如果你曾這麼做,應該能體會它有多麻煩--程式碼裡面到處得加上註解,標示哪一段是為何修改、哪一段必須等到所有新版功能完成時才能交付……諸如此類的,以便在整合兩邊的程式碼時不會亂掉。但事實上,這種動作既麻煩,又容易出錯,到最後可能連程式設計師自己都分不清楚哪個部分要交付,哪個部分不要。

既然如此,何不試試用工具來減輕自己的負擔?

廉價複製

與其用手動複製檔案、剪貼程式碼的方式管理版本,我們可以用 Subversion 的廉價複製功能來建立那些支線的版本(如上例中的 HR_NewFeature),並視需要進行版本之間的合併。

這裡的廉價複製,指的是 svn copy 指令。但為什麼說「廉價複製」呢?因為當你利用 svn copy 來複製資料夾的時候,雖然在本機的工作目錄中確實可以看到兩個資料夾和複製的檔案,但檔案庫裡面並沒有真正複製所有的檔案內容,而只是類似建立連結的動作,或者只儲存有變動的部分而已。這種複製動作的負載輕、成本低,故曰廉價。
可以這麼說:Subversion 檔案庫裡面其實沒有「分支」這種東西,所有的變動都只是之前版本的另一個廉價複製版本。我們只是利用廉價複製的功能,產生一個資料夾的複本,並將它視為分支,如此而已。

決定分支的存放位置

延續前面的案例,現在我們要開始為人事系統(HR)建立支線版本。首先碰到的問題,是支線的目錄要放哪?以 Web 專案來說,分支的目錄顯然不能放在 Web 資料夾底下,因為如此一來,同一個 Web 專案將會因為建立分支(廉價複製)的緣故而產生類別名稱衝突的情形。

我們可以這樣安排分支的目錄:



也就是在專案(檔案庫)的根目錄下建立 branches 資料夾,以便將各類原始碼的支線納入此目錄下管理。這種方式的一個優點,是在主線與支線的版本之間來回切換與合併時,從檔案的 URL 前面幾個字元就能分辨是主線還是支線,不容易搞混。當然這只是一種選擇,不代表最好的方式。如果你一開始就想到將來可能需要建立分支,在建立檔案庫時,就可以在根目錄下各建一個 trunk 和 branches 來存放主線與支線的檔案。

或許有點多餘,但還是註明一下:分支的目錄不可跨檔案庫(即不能將分支建立在別的檔案庫中)。
建立分支

首先把作為分支的上層目錄建立妥當,也就是 branches\Web,並確認這些目錄及主線的工作複本(working copy)都已送交至檔案庫。

接著在想要產生分支的資料夾(HR)上點右鍵 > TortoiseSVN > Branch/tag...。參考下圖:


你會看到如下圖的對話窗:


注意:若 HR 分支的上層目錄 branches\Web 沒有事先建立且送交至檔案庫,在建立 HR 分支時會失敗(路徑不存在)。

對話窗左下角的「Switch working copy to new branch/tag」核取方塊若有勾選,表示分支建立完成後,順便把目前的工作目錄切換至支線版本--通常會這麼做。當然你也可以選擇先不要切換到支線版本,等你開始要在工作目錄下開發支線版本的程式時,再利用 TortoiseSVN 的 switch 功能來切換。

Tip:第一次建立分支,可能會有點疑慮,擔心哪個步驟做錯了,或者不清楚發生了什麼事。這裡有個小建議,分支建好之後,不妨對 branches 目錄做 SVN Update,你會看到 branches\Web 底下多出一份 HR 目錄的拷貝(啊!原來分支就是 copy 嘛)。當然,你不用直接修改 branches 底下的檔案,而應當把主線的工作目錄(MyProject\Web\HR)切換到支線,再對其修改。原因很簡單:這樣你做的修改才會被編譯、執行。

在撰寫程式時,都是針對本機的同一個工作目錄,以此例而言,就是 MyProject\Web\HR。當你要修改主線的版本時,就用 switch 功能切換到主線;同樣的,要修改支線版本時,就切到支線。你所要牢記的,就是每次修改程式之前,先確認目前的工作目錄是對應到主線還是支線版本(否則你還是可能會亂掉)。

Q & A

問:我們公司有一台測試用的 app server,有時候,使用者或測試人員想要測試目前正式環境的版本,有時候又要切換到新開發的版本,這種情況也能用分支的方式解決嗎?

答:一樣適用。看他們想測哪個版本,就在測試 server 上用 SVN 的 switch 功能切換主線或支線版本。
================================================
問:這樣來回切換版本,如果支線版本很多,我的腦袋可能還是會亂掉,造成版本錯亂,這樣.....用工具來管理真的有比較省力?

答:如果真的碰到支線版本眾多,又常得來回切換的情形,不用工具管理只會更糟(想像你要記住的版本有多少種、將來如何合併)。若情況嚴重到連工具都幫不了忙,或許該停下腳步,回頭想想為什麼那些需求會如此反覆無常。
================================================
問:我怎麼知道目前工作目錄下的版本是主線還是支線?

答:TortoiseSVN 的 relocate 或 switch 功能都會顯示目前所對應的版本的 URL。


下一篇: 使用 TortoiseSVN 處理版本的分支與合併(二)

2 則留言:

技術提供:Blogger.
回頂端⬆️