講解 Subversion 分支與合併:以 TortoiseSVN 為例

  分享到噗浪!

在實務的版本控管情境中,套用分支與合併應該是最方便不過的了,會用的人可以得到許多版本控管的好處,但不會用的人卻會因為不理解而害怕使用它,由於 Subversion 1.5 開始新增了 Merge Tracking 功能,可有效降低維護分支的負擔,所以能學會分支與合併的技巧對整個版本管理流程來說會有非常大的幫助,今天我就來講解幾個利用 TortoiseSVN 實際的操作分支與合併的例子。

如下圖是一個很常見的分支示意圖,當你想在 trunk 發展一個新功能時,你可以透過 svn copy 的方式將整個 /calc/trunk 廉價複製/calc/branches/my-calc-branch,當 /calc/branches/my-calc-branch 分支完成所有新功能開發後,再將所有變更一次合併回 /calc/trunk 開發主線。

我講的 svn copy 其實就是對應到 TortoiseSVN 的 Branch/tag 功能

 

使用時應注意以下:

  1. 你要廉價複製的來源路徑
  2. 你要廉價複製的目的路徑 (「複製」就等同於「分支」,這是 SVN 附加上去的意義 )
  3. 寫下你為什麼要建立這個分支、用途是什麼,這訊息可以給團隊成員或版本經理看
  4. 我們可以在執行 Copy (Branch/tag) 的同時順便將你的「工作目錄」切換至「分支的路徑」

這時我們可以看一下 trunk 這個目錄的屬性,並切換至 Subversion 頁籤,你會發現該「工作目錄」所對應到的 Subversion 路徑已經變更到 /calc/branches/my-calc-branch 了。

但為了怕初學者混淆,我還是先將 /calc/trunk 切換回原本的 SVN 路徑:

這裡有幾點注意:

  1. 這裡是你的「工作目錄」(Working Copy)
  2. 這裡才是你要將「工作目錄」切換到的 SVN 路徑,也就是將 /calc/branches/my-calc-branch 切換至 /calc/trunk 路徑

這時你便可以開始在 /calc/branches/my-calc-branch 發展你這次想要新增的功能,且不會影響到其他團隊成員正在發展或維護的 /calc/trunk 開發主線。

也許過了一段時間,原本的 /calc/trunk 開發主線可能已經有其他團隊成員陸續修正了一些 Bugs,但這時你的分支 /calc/branches/my-calc-branch 就可以直接套用 開發主線 ( /calc/trunk ) 的更新,除了避免重複的工作外 (重複除錯),也可以避免版本的衝突發生,因為兩個人改同一個已知的 Bug 可能會因為用不同方法除錯或命名的方式不一致而發生衝突。

經常將 開發主線 ( /calc/trunk ) 的變更透過 svn merge 合併至 分支線路 ( /calc/branches/my-calc-branch ) 是一個非常好的習慣,這樣才不會讓你因為脫離 開發主線(trunk) 過久而導致將 分支線路 ( /calc/branches/my-calc-branch ) 合併回 開發主線 ( /calc/trunk ) 時發生許多版本衝突。

 

開發主線 ( /calc/trunk ) 合併至 分支線路 ( /calc/branches/my-calc-branch ) 通常選第 1 個,也就是 [Merge a range of revisions]

在 Merge 的視窗有以下注意事項:

  1. 設定要合併的來源,由於我們打算從 開發主線 ( /calc/trunk ) 合併分支這段時間所產生的變更至 分支線路 ( /calc/branches/my-calc-branch ),所以合併的來源要選擇 /calc/trunk 才對!
  2. 合併的結果會直接與目前「工作目錄」(Working Copy) 做比對,並修改目前工作目錄中的所有檔案。因此建議在做合併之前可以將所有尚未 commit 的檔案先 commit 到版本庫,避免不必要的衝突事件發生。

在正式進行合併(Merge)之前,建議先執行 Test merge 看看是否會發生什麼事!

若無異狀則可直接按下 [Merge] 按鈕進行合併動作,這時從 開發主線 ( /calc/trunk ) 分支出來的到目前工作目錄的版本就會做個比較,然後直接套用變更到你現有的檔案、目錄或屬性裡。

在合併之後如果沒有發生衝突,不代表真的沒衝突,所以必須再次對原始碼做出驗證後才能 commit 進版本庫,建議可參考以下流程:

  1. 將專案進行建置(Build)
  2. 如果沒問題再對專案進行單元測試(Unit Testing)或手動測試(Manual Testing)
  3. 如果都沒問題再 commit 目前合併無誤的版本到版本庫!

最後我們的 my-calc-branch 分支已經將新功能開發完成且測試無誤,所以要將 分支線路 ( /calc/branches/my-calc-branch ) 的最終版本合併回 開發主線 ( /calc/trunk ),這時的手續如下:

分支線路 ( /calc/branches/my-calc-branch ) 合併回 開發主線 ( /calc/trunk ) 通常選第 2 個,而特別選擇 [Reintegrate a branch] 這個選項是很重要的,因為這有以下好處:

  1. 讓 Subversion 能知道 開發主線 ( /calc/trunk ) 是從哪個分支、哪些版本合併進來的
  2. 有效節省 Subversion Repository (SVN儲存庫) 的空間,因為不用重複儲存分支的所有變更資訊
  3. 可以產生 Revision graph 得知專案開發的分支狀況

一樣可以先 測試合併(Test merge) 再正式進行 合併(Merge)

合併完後再將變更 commit 到版本庫

 

 

分支線路 ( /calc/branches/my-calc-branch ) 合併回 開發主線 ( /calc/trunk ) 並 commit 了之後,該分支就沒用了,Subversion 也不會繼續追蹤這個分支的變更 (因為之前已經 Reintegrate 過了),所以建議將該分支刪除。

刪除後要記得 commit 才能將「刪除動作」寫入到 Subversion Repository (SVN儲存庫) 中

 

以上就是一個 Subversion 分支與合併的完整過程,但有許多很細部的觀念我很難在一篇文章裡講清楚,如有時間建議多閱讀 Subversion 線上文件,當你建立起更多更完整的觀念後,對 Subversion 甚至是其他版本管理工具應該都能夠更加得心應手!

相關連結

此文章由 will 發表於 2010/1/29 上午 12:33:25

永久連結 | 評論 (23) | 此文章的RSSRSS comment feed |

分類: Subversion

標籤: , , , , , , ,

評論

一月 29. 2010 12:49

anonym

...寫下擬為什麼要建立這個分支,用途是什麼,這訊息可以給團隊成員或版本經理看...
請問擬是不是你??

anonym

一月 29. 2010 21:07

Will 保哥

anonym: 感謝指正錯誤,錯字已修正。 Smile

Will 保哥 Taiwan

二月 2. 2010 16:58

Gower Lin

請問版主, 有沒有計畫要出本 TortoiseSVN 實例應用技巧 之類的書籍? 好期待~~  

Gower Lin

二月 8. 2010 02:45

Willie

請教一下,不知道你們在使用 SVN 時,有大量的使用 svn 的 merge / reintegrate 嗎?

svn 1.5+ 之後會帶 merge info,試圖解決過去要手動紀錄 revision merge 的紀錄;但一來這讓 svn status / diff 會顯示很擾人的 properties change list,更重要的是,

我發現 reintegrate 很容易有問題? (svn book 我翻過一次,自認基本的操作應該不至於不清楚)

我剛去查了一下幾個用 svn 的 opensource project,才發現似乎都沒有在用 svn 的 merge,看起來是靠 diff / patch 來手動合併。不知您有沒有遇到類似的困擾?

如果這問題不解決,大概只能投靠 Mercurial 了... Orz

Willie Taiwan

二月 8. 2010 02:48

Willie

補充一下,我這邊跑的是 svn 1.6.6,有大量的使用 svn:external ,加上過去是從 svn 1.4 上來的 repo,所以 merge info 並不完整...

我自己的經驗是 svn 的 merge 不太好用 (即使是 1.6+ 也是一樣,那個 tree conflict 其實有時也很擾人),相對來說 Mercurial 就直覺方便多了...

Willie Taiwan

二月 8. 2010 18:08

Will 保哥

Willie:

我們雖然沒有很大量的使用 svn 的 merge / reintegrate,但我不知道你的「大量」是什麼意思?我們幾乎不用指令列操作 SVN,都是利用 TortoiseSVN 進行操作,過程並未有任何問題。

另外,svn:external 我沒在用,因為會把 Working Copy 弄得很複雜,您提到的問題我沒經驗,所以無法給你建議。但 tree conflict 的確很擾人,所以我們盡可能不要弄太複雜的 tree,否則過於複雜的版本控管有礙團隊建構。

Will 保哥 Taiwan

二月 8. 2010 18:23

Willie

Hi,

謝謝您的回覆,我用「大量」一詞不太精確,應該說「頻繁」的使用 branch / merge 比較正確。

不過 tree conflict 只要在不同的 branch 作 rename 的動作就會出現,要完全避免好像無解 (除非不重構?)... 我會再找看看有沒有好的解法... 多謝!!Smile

Willie Taiwan

十二月 10. 2010 15:19

Willie

過了 n 個月後,我家現在正準備遷徙至分散式版本控制系統 Mercurial...

SVN 這個問題短時間之內我不認為有任何比較好的 workaround 可以避免,換版控系統是比較斬草除根的方式...

Willie Taiwan

十二月 10. 2010 15:30

Will 保哥

Willie: 為什麼不用 Git ?

Will 保哥 Taiwan

十二月 10. 2010 16:05

Willie

家裡有 .NET team... 我評估過 Bazzar / Git / Mercurial ,其中 Git 因 Windows 中文支援問題在一開始就出局了... :/

Bazzar 雖然有 unicode filename support 但我個人實測還是有些許問題,尤其是他的 performance 還是沒有宣稱的那麼好....

Mercurial 的部份 TortoiseHG 已經算堪用,加上配合 Windows Power Shell (我打算一開始先從 CLI 開始講) 也都沒啥問題,所以...

Willie Taiwan

六月 13. 2011 14:40

freedom

不错,讲解得比较详细。
谢了。

freedom People's Republic of China

八月 24. 2011 17:39

steven

請問..
若server端為第四版的,
而我把本地最新的commit上去(這時會,變為第五版的)
但,我是想它取代為第四版
.這時,要如何去合併及操作(這時,在server中的檔案內容和本地的檔案不同時)

謝謝

steven Taiwan

八月 24. 2011 17:55

Will 保哥

steven: 版本控管會保留所有紀錄,所以「預設」不會讓你取代第四版的內容,後來才 commit 的版本一定是第五版。

Will 保哥 Taiwan

十一月 30. 2011 18:04

Mark Huang

請問您的圖片都是怎麼做的?像是標號碼、箭頭、框框之類的,做的蠻專業的耶。

Mark Huang Taiwan

十一月 30. 2011 18:13

Will 保哥

Mark: 我是用 SnagIt 軟體製作的,這是一套商用軟體。

Will 保哥 Taiwan

二月 22. 2012 21:41

小胖

寫的實在超級好, 真的太感謝了 !!

小胖 Taiwan

三月 13. 2012 11:40

young

請問一下,切換(switch to)到底是幹甚麼用的? 很簡單的概念說明即可.
我只使用很簡單的TortoiseSVN功能。有時候在"tags" path 上工作時,
會看到如此的訊息,我看不懂也不管他:
Your working copy appears to be on a tag path!
You should first switch to a branch or the main trunk before committing.
Do you want to commit anyway?
感謝您。

young Taiwan

三月 13. 2012 12:45

Will 保哥

young: 切換(switch to)的意思是「切換目前的工作目錄到另一個路徑」。

例如你現在的工作路徑是在 SVN 的 /trunk/ 路徑下,當你想要開發分支的時候就可以在你把 trunk 下的檔案都 commit 上去之後先做一次 Copy (Branches/Tags) 的動作將 /trunk 複製一份到 /branches/trunk-120313,通常在做這個動作時 TortoiseSVN 就會問你要不要把工作目錄切換過去。如果你沒有切換的話,就可以自己再用切換(switch to)的功能將工作目錄切換到 /branches/trunk-120313,這樣你就可以在 Branches 目錄下工作了。

因為 Tags 目錄本來就不是用來做開發的,而是用來將特定版本「封存」用的,他只是問你是不是真的要在 tags 目錄 commit 而已,你應該還是可以繼續 commit 的。

Will 保哥 Taiwan

三月 14. 2012 19:06

young

tags ==> 「封存」,很傳神!一看就瞭。
switch看來是"高級"用途,等遇到了再來傷腦筋吧。
謝謝 Will。

young Taiwan

三月 21. 2012 10:02

CP

請問一下,如果我的程式架構是下面這樣
1.MainApp(主程式,編譯出來是EXE)
2.ABC01(模組,C#專案,編譯出來是DLL,可個別編譯)
3.ABC02(模組,C#專案,編譯出來是DLL,可個別編譯)
4.ABC....

放到SVN的時候都是放在一個版本庫裡面嗎?還是要將模組個別一個版本庫

CP Taiwan

三月 22. 2012 09:27

Will 保哥

CP: 放在一個版本庫裡比較容易管理,如果要放成多個,也可以透過 svn:external 屬性來把多個專案整合在一個工作目錄下。相關連結請參考: http://bit.ly/GErZLx

Will 保哥 Taiwan

五月 14. 2012 17:49

Litfal

保哥您好:
我最近要將程式分出去,做成base很像但是不少東西又不一樣的新軟體。
因為是新軟體所以分出去後就不會再併回來了。

但由於base一樣,主線修的bug,或是以後增加新的feature,我想讓分支也跟著更新。
這樣的話適合使用Branch/tag的做法嗎?

Litfal Taiwan

五月 14. 2012 18:06

Will 保哥

Litfal: 當然適合,你可以將 base 的「部分變更」套用到「分支」上,這樣就可以把相同的 Bug 也修正到分支上面的程式碼。

Will 保哥 Taiwan

新增評論


( 您輸入的Email不會顯示於網站上 )

  Country flag

biuquote
  • 評論
  • 線上預覽
Loading