說來慚愧,鄙人從事開發多年,使用svn已經好幾個年頭了,可是卻僅限於update、commit、compare之類的操做,最近想到github上學習別人寫的NIO源碼,順便去熟悉git的使用,可是一想到svn,我內心虛了:用了那麼多年卻對其只知其一;不知其二,就連最基本的權限分配都沒有作過,更別說進行分支拉取和合並了,何談去get其餘技能?作技術的仍是要踏實一點,近一年來,我都在對以前未深刻的領域進行掃盲,因此,註定svn是繞不過的坎,因而乎開始各類查資料,安裝svn服務端(Virtual SVN)和客戶端(TortoiseSVN),比對網上的博文進行各類嘗試,不能說過程痛苦,可是當你在雲裏霧裏摸索的時候挺難受的吧(順便說下,在學習的時候精力必定要集中!對我而言,順便塞上耳塞聽音樂工做效率是事半功倍,哈哈哈~)~不廢話了,今天這篇博文就講講SVN裏面比較高級的操做:建立分支(branch)、將主幹(trunk)中的代碼合併到分支(branch)、將分支(branch)中的代碼合併到主幹(trunk)中~html
說到分支和主幹,我想很多coder也是比較少接觸吧,畢竟不少時候,咱們想着的仍是如何趕進度~之因此出現分支和主幹,就是但願主幹和分支兩份代碼能夠各自進行獨立的管理互不影響,在須要的時候再進行合併。試想這樣一種場景:公司項目已經完成一個階段的開發計劃,這時候拉取一個branch專門用來測試以及BUG修復,而原先trunk上面的代碼還能夠繼續往下開發,互不影響,等測試的branch問題修復以後,將這個branch「合併」回trunk。這樣trunk和branch能夠在互不干擾的狀況下各自作本身的事兒,最後再進行整合,合併過程當中有可能會有衝突,這個並不麻煩,等出現衝突的時候自行百度,我相信大家能夠解決的,若是仍是暈乎乎,歡迎加羣交流~git
接下來我就來講說如何建立分支(branch)、將主幹(trunk)中的代碼合併到分支(branch)、將分支(branch)中的代碼合併到主幹(trunk),首先說明一下筆者當前測試環境:github
準備工做(以上客戶端服務端自行安裝,除了安裝路徑看本身喜愛以外,其餘都按照默認設置,點擊「下一步」吧):服務器
1)建立repositoryapp
打開Virtual SVN,在左側列表中,右鍵Repositories,新建一個repository,名字隨意,格式筆者是選擇FSFS,Repository Structure筆者選擇Single-project repository******,這樣方便後面的描述,爲了測試的方便,在選擇「Repository Access Permissions」的時候,選擇全部人SVN的user都有訪問這個repository的權限(user能夠在Virtual SVN的左側列表Users節點右鍵,進行新增)svn
2)Check out trunk目錄到本地學習
首先複製剛剛新建的repository下trunk的SVN URL測試
在本機隨意一個目錄新建一個空目錄,好比筆者在d盤新建了一個svntrunk的目錄,而後右鍵=>SVN Check out,將trunk的svn地址複製到「URL of repository」那一欄,而後點擊「OK」spa
3)在D:\svntrunk目錄下新建一個目錄(名稱設爲project),而後在新建的目錄下新增兩個text文件:1.txt(文件內容:111111),2.txt(文件內容:222222),而後右鍵這個project目錄,先Add,而後進行commit:.net
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)中的代碼合併到主幹(trunk)
首先,就像以前將主幹(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)這一節有講),而且須要瞭解合併的原理,那麼拉取分支和合並的操做並非什麼難事。若有什麼疑問,請加羣交流~
一、http://blog.csdn.net/zhuyong0722/article/details/8965095
二、http://blog.csdn.net/wjtxt/article/details/8623262
三、http://www.cnblogs.com/firstdream/p/5632296.html
爲方便沒有博客園帳號的讀者交流,特地創建一個企鵝羣(純公益,非利益相關),讀者若是有對博文不明之處,歡迎加羣交流:261746360,小杜比亞-博客園