SVN分支/主干Merge操作小記


一、前言

  說來慚愧,鄙人從事開發多年,使用svn已經好幾個年頭了,但是卻僅限於update、commit、compare之類的操作,最近想到github上學習別人寫的NIO源碼,順便去熟悉git的使用,但是一想到svn,我心里虛了:用了那么多年卻對其一知半解,就連最基本的權限分配都沒有做過,更別說進行分支拉取和合並了,何談去get其他技能?做技術的還是要踏實一點,近一年來,我都在對之前未深入的領域進行掃盲,所以,注定svn是繞不過的坎,於是乎開始各種查資料,安裝svn服務端(Virtual SVN)和客戶端(TortoiseSVN),比對網上的博文進行各種嘗試,不能說過程痛苦,但是當你在雲里霧里摸索的時候挺難受的吧(順便說下,在學習的時候精力一定要集中!對我而言,順便塞上耳塞聽音樂工作效率是事半功倍,哈哈哈~)~不廢話了,今天這篇博文就講講SVN里面比較高級的操作:創建分支(branch)、將主干(trunk)中的代碼合並到分支(branch)、將分支(branch)中的代碼合並到主干(trunk)中~

二、正文

  說到分支和主干,我想不少coder也是比較少接觸吧,畢竟很多時候,我們想着的還是如何趕進度~之所以出現分支和主干,就是希望主干和分支兩份代碼可以各自進行獨立的管理互不影響,在需要的時候再進行合並。試想這樣一種場景:公司項目已經完成一個階段的開發計划,這時候拉取一個branch專門用來測試以及BUG修復,而原先trunk上面的代碼還可以繼續往下開發,互不影響,等測試的branch問題修復之后,將這個branch“合並”回trunk。這樣trunk和branch可以在互不干擾的情況下各自做自己的事兒,最后再進行整合,合並過程中有可能會有沖突,這個並不麻煩,等出現沖突的時候自行百度,我相信你們可以解決的,如果還是暈乎乎,歡迎加群交流~

  接下來我就來說說如何創建分支(branch)、將主干(trunk)中的代碼合並到分支(branch)、將分支(branch)中的代碼合並到主干(trunk),首先說明一下筆者當前測試環境:

  1. Virtual SVN 1.9.5(傳送門:https://www.visualsvn.com/server/download/
  2. TortoiseSVN 1.9.5(傳送門:https://sourceforge.net/projects/tortoisesvn/files/1.9.5/Application/

   准備工作(以上客戶端服務端自行安裝,除了安裝路徑看自己喜好之外,其他都按照默認設置,點擊“下一步”吧):

  1)創建repository

  打開Virtual SVN,在左側列表中,右鍵Repositories,新建一個repository,名字隨意,格式筆者是選擇FSFS,Repository Structure筆者選擇Single-project repository******,這樣方便后面的描述,為了測試的方便,在選擇“Repository Access Permissions”的時候,選擇所有人SVN的user都有訪問這個repository的權限(user可以在Virtual SVN的左側列表Users節點右鍵,進行新增)

         

    

    

    

              

  2)Check out trunk目錄到本地

  首先復制剛剛新建的repository下trunk的SVN URL

  

 

  在本機隨意一個目錄新建一個空目錄,比如筆者在d盤新建了一個svntrunk的目錄,然后右鍵=>SVN Check out,將trunk的svn地址復制到“URL of repository”那一欄,然后點擊“OK”

   

  3)在D:\svntrunk目錄下新建一個目錄(名稱設為project),然后在新建的目錄下新增兩個text文件:1.txt(文件內容:111111),2.txt(文件內容:222222),然后右鍵這個project目錄,先Add,然后進行commit

  

       

  

  

  

  4)創建分支(branch)(嘮叨一下,分支是創建在SVN服務器的repository中,而merge是合並在開發者本地)

   右鍵D:\svntrunk\project文件夾,選擇TortoiseSVN->Branch/tag,在彈出的對話框中,To path輸入分支存放在repository的相對目錄,這邊注意:project01不能先創建,不然會報project01已經存在,不能創建分支!在log message中輸入創建分支的日志,這對后續了解這個分支創建的目的有一定意義。在log message輸入欄下面,還有一個Create copy in the repository from的選項,這個選項的目的是為了讓開發者選擇用哪份源碼作為創建的版本 ,第一個是trunk中最新的版本,第二個用戶可以選擇trunk中指定的版本(通過序號標識),第三個是將工作拷貝作為創建分支的版本

  

  上步點擊OK之后,創建分支完成,就是這么簡單,現在請先記住,我們是以trunk中版本序號是2的工程作為創建分支的版本,這個對后續的合並有意義~(這邊順便說下,在一個repository,版本號是一個全局資源,不管是trunk、branch還是tag,他們使用的版本號不會重復,比如現在trunk已經用掉2這個版本號,那么分支就只能往下一個,用3)

  

  

   5)分支(branch)中的代碼合並(merge)到主干(trunk)

  特別特別注意:要用好“合並”操作,一定要理解“合並”操作的真正意思。“合並”的意思不是簡單的文件合並,而是“操作合並”。如果有知道redis的AOF持久化的同學,應該比較容易理解。我們首先看下SVN上某個版本:

  

 

   svn上每個提交版本,都對應一組操作,你可能在本次提交中修改、新增、刪除了某些文件,這些操作和這個版本對應,當進行Merge的時候,是將這些操作應用到本地Working copy中,這就是“合並”的本質:將某個版本(或者某個版本范圍)的操作應用到本地的working copy!理解這點很重要!(Merge的type為“Merge a range of revisions”時的原理)

  下面還有一個type為“Merge two different trees”的“合並操作”,本質和上面的類似,這邊涉及From和To兩個URL,這邊的意思是比較以To為基准,從From到To需要經過哪些操作,將這些操作應用到本地的Working copy,比如From里面有個文件a.txt,而To里面沒有這個這個文件,那么這邊就會有個操作:"delete a.txt",即使不能刪除本地的a.txt,但是你如果執意要merge,那么這個刪除的操作,肯定會應用到本地的Working copy。如果to里面有個b.txt文件,From里面沒有,那么From要到To的話,這邊就有一個“add b.txt”的操作,更新的話,類似。

 

 

 

        首先,就像之前將主干(trunk)Check out到本地一樣,將svn服務器上面的分支(branches)Check out到D盤svnbranches目錄:

  

  現在假設主干(trunk)和分支(branche)並行開發,主干(trunk)project下1.txt的文件內容改為121212,分支(branch)中project1下面增加一個3.txt文件,文件內容為:333333

  右鍵主干中project文件夾,選擇TortoiseSVN->Merge,這時會彈出一個Merge type讓你選(TortoiseSVN1.9.5這個版本只有兩個選項,網上有些博文有三個選項),Merge type的選擇還是很有講究,並且也是很容易搞錯的,下面會具體來說說:

  

  我們先來說說“Merge a range of revisions”這個選項:

  我們選中這個選項,然后點擊“Next”,會看到如下界面,因為我們是要將分支(branch)合並到主干(trunk),所以這邊URL to merge from選項要選擇服務器上面需要合並到主干(trunk)的分支(branch)地址(注:前面有提過,合並是合並到本地的working copy,所以一般合並之前,最好將本地working copy代碼先更新一遍,有沖突的解決沖突,並且將未提交的代碼提交,以防在合並之后,未提交的代碼丟失),這邊有個Revision range to merge選項,當選擇all revisions進行merge的時候,TortoiseSVN做了怎么樣的操作呢?其實就是:diff and apply。diff是比較URL to merge from指定的工程最新一個版本和最初的一個版本的差異,假設最新版本是r-last,最初的版本r-first,r-last相對r-first而言,增加了文件a,修改了文件b,那么在合並的時候,就將“增加文件a,修改文件b”的操作應用在本地的working copy上面去,這就完成了合並;假設選擇的是specific range,那么用戶可以選擇一個版本范圍,也可以單獨指定一個版本或者不填寫任何值(此時相當於選all revisions),假設用戶指定了版本r1-r3,其中r1新增了文件a,r2新增了文件b,r3刪除了文件c,那么在合並的時候TortoiseSVN就會將“新增文件a,新增文件b,刪除文件c”應用於本地的 working copy,這樣就完成了合並~

  (ps:這邊還有一個Reverse merge復選框,恢復之前的合並。假設我們剛剛做的merge有問題,需要將本地的working copy恢復成merge之前的,那么就需要將之前應用於本地working copy的操作全部回退,操作和merge基本一樣,只是最后,需要復選這個Reverse merge復選框)

  

  上步選擇了Revision range to merge之后,點擊“Next”,進入如下界面,這時我們就可以看到如下界面:

  

  全部使用默認的選項,然后在點擊Merge之前,可以先點擊Test merge按鈕,測試一下merge之后的效果:

  

  如上圖所示,分支(branch)版本新增的3.txt文件最終會合並到本次working copy中,最后將本地working copy中的3.txt提交到svn中,這樣就完成了分支到trunk的合並了~

  

  我們再來說說這個“Merge two different trees”,從它自己選項的解釋來看,是將兩個不同的分支(branch)合並到本地working copy中,當然,我們也可以用這個選項將分支(branch)修改的內容合並回主干(trunk)。選擇Merge two different trees,點擊Next

  

  上步之后,會出現如下對話框,注意,我們現在是將分支(branch)合並回主干(trunk),這個時候,我相信很多人想當然的認為Fom處填寫的應該是分支(branch)的URL,而To,應該是主干(trunk)的URL,因為是從分支(branch)到主干(trunk)啊,然后事實並非如此!之前在創建分支(branch)這一節,有讓讀者記住拉取分支(branch)時,主干(trunk)的版本號,當時主干(trunk)的版本號是2,所以From處的URL應該寫主干(trunk)的URL,Revision應該選2(其實trunk revision為2的版本,其實也就是branch的第一個版本,所以這邊From可以選擇主干拉取分支的版本,也可以選取分支最開始的版本),而To處的URL應該選分支的URL,Revision選HEAD Revision,也就是選最新的分支版本。現在就來說說為什么要這樣填寫:此處進行merge的時候,進行的操作也是diff and apply,將To處URL和revision指定的某個版本,與From處URL和Revision指定的某個版本進行對比,對比是有順序的,這個怎么理解呢?比如現在To處的為工程project1,From處的為工程project,如果project1相對於project而言,有文件a,沒有文件b,換句話說project1相對於project而言,“新增了a,刪除了b”,那么此處merge的結果就是會將“新增a,刪除b”的操作應用於本地working copy的工程,那為什么From處的project不能指定為最新的Revision呢,既HEAD Revision?試想一下,假如主干(trunk)在拉取了分支(branch)之后,主干(trunk)和分支(branch)都有在並行開發,那么必然主干(trunk)上會有新增的功能,這樣就會有新增的代碼,這些代碼在分支(trunk)上並不存在,在To和From比較過程中,就會出現“刪除xxx”的操作,這在merge過程中會應用在本地working copy中,本來這個“xxx”是主干新功能的代碼,在將分支合並過來的時候,不應該刪除,所以不能用主干最新的版本和分支最新的版本做對比,應該是將當時拉取分支的時候的主干版本和當前最新的分支版本進行對比,應用到本地working copy中才對,所以這邊的From必須選取當時拉取當前分支的主干版本,不然主干上面新增的代碼會丟失,之前我對From和To的順序,以及revision的選取也是迷糊了大半天,我希望對讀者而言,我這邊已經說清楚了~如果還有什么不清楚的歡迎加群交流~

       

  上步之后,點擊Next,進入下面這個頁面,同樣,在最終merge之時,點擊Test merge

  

  點擊Test merge之后,可以看到最終合並之后的效果

  

  6)主干(trunk)中的代碼合並到分支(branch)

  這邊的操作和分支(branch)合並到主干(類似),需要注意的是,Merge type如果選擇“Merge a range of revisions”,那么范圍的起始版本應該為拉取分支時的主干版本,結束版本應該為trunk最新的版本;如果選擇“Merge two different trees”,那么From必須是選取拉取分支時的主干的版本,或者分支的第一個版本,To必須是主干最新的版本

  

  最后總結一下:不管選取哪個Merge type,都能完成主干到分支、分支到主干的合並,需要注意的是,在選擇“Merge two fifferent trees”時From和To對應的URL所代表的含義(5)分支(branch)中的代碼合並到主干(trunk)這一節有講),並且需要了解合並的原理,那么拉取分支和合並的操作並不是什么難事。如有什么疑問,請加群交流~

三、鏈接

1、http://blog.csdn.net/zhuyong0722/article/details/8965095

2、http://blog.csdn.net/wjtxt/article/details/8623262

3、http://www.cnblogs.com/firstdream/p/5632296.html

四、聯系本人

  為方便沒有博客園賬號的讀者交流,特意建立一個企鵝群(純公益,非利益相關),讀者如果有對博文不明之處,歡迎加群交流:261746360,小杜比亞-博客園


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM