【軟體工程技術之程式版本控制】SVN的使用——基本知識,Server搭建與Client日常使用維護

來源:互聯網
上載者:User

作者:gnuhpc 
出處:http://www.cnblogs.com/gnuhpc/

 

本文綜合修改自網上幾篇Blog和自己手頭的資料,原始出處均不詳,如有著作權問題請及時與我聯絡並提供原始文字連結。這裡以Windows下用戶端和伺服器進行舉例,Linux有對應,原理相同。

一、基本知識:

1.為什麼要使用SVN?

· 程式員編寫程式的過程中,每個程式都會產生很多不同的版本.

· 這就需要程式員能有效管理代碼,在需要的時候可以迅速,準確取出相應的版本

· 任何需要管理頻繁資訊改變的地方都需要它,這就是Subversion的舞台

2. Subversion是什麼?

· Sub Version(簡稱SVN)是版本管理工具

· Subversion是一個自由/開源版本控制系統

· 一組檔案存放在中心版本庫, 記錄每一次檔案和目錄的修改

· Subversion可以通過網路訪問它的版本庫

· 任意數量的用戶端可以串連到版本庫,讀寫這些檔案.

· 通過寫,別人可以看到這些資訊,通過讀資料,可以看到別人的修改

3.Subversion的特性有哪些?

· 版本化的目錄:Subversion實現了一個可以跟蹤分類樹更改的“虛擬”版本化檔案系統

· 真實的版本曆史:可以新增一個具有乾淨曆史的檔案

· 原子提交:可以讓使用者構建一個要提交修改的邏輯塊,防止部分修改提交到版本庫

· 版本化的中繼資料:每一個檔案或目錄都有一套屬性—鍵和它們的值

· 可選的網路層:在版本庫訪問方面有一個抽象概念,利於人們去實現新的網路機制

· 一致的資料操作:檔案是建立在二進位檔案區別演算法基礎上的

· 有效率的分支和標籤:建立分支與標籤時只是拷貝整個工程,使用了一種類似於永久連結的機制

· 可修改性:由一系列良好的共用C庫實現,具有定義良好的API

4.Subversion的原理是什嗎?

鎖定-解鎖


拷貝-修改-合并

Subversion主要採用拷貝-修改-合并模型,配合鎖定-解鎖模型管理資料的共用

5.Subversion的基本工作流程是什嗎?

二、SVN伺服器的搭建與配置:

1.啟動:安裝好VisualSVN Server後,運行VisualSVN Server Manger,下面是啟動介面:

2.添加一個程式碼程式庫【Repository】:如:

按所示,建立新的程式碼程式庫,在所示的文字框中輸入程式碼程式庫名稱:

注意:中的CheckBox如果選中,則在程式碼程式庫StartKit下面會建立 trunk、branches、tags三個子目錄;不選中,則只建立空的程式碼程式庫StartKit。

點擊OK按鈕,程式碼程式庫就建立成功了。

3.安全性設定:

在左側的Users上點擊右鍵:

輸入上面的資訊,點擊OK,我們就建立一個使用者了。按照上面的過程,分別添加使用者 Developer1、tester1、manager1,好了,我們開始添加這些使用者到我們剛才建立的項目裡:

點擊中的"Add..."按鈕,在中選擇我們剛才添加的使用者,點擊OK按鈕:

說明:大家可能注意到了中的Groups,是的,你也可以先建立組,把使用者添加到各個組中,然後對組進行授權,操作比較簡單,在此略過。

按照所示,分別對使用者【或組】進行授權:

點擊"確定"按鈕,上面的使用者就具有了存取碼庫的不同許可權。

二、SVN用戶端的使用方法——TortoiseSVN的基本使用方法

1.匯入原始碼到SVN伺服器

假如我們要把項目StartKit的原始碼簽入到SVN Server上的程式碼程式庫中裡,首先右鍵點擊StartKit檔案夾,這時候的右鍵菜單如所示:

點擊Import,彈出下面的表單,其中http://zt.net.henu.edu.cn/ 是伺服器名,svn是代碼倉庫的根目錄,StartKit是我們在SVN Server上建立的一個程式碼程式庫:

說明:左下角的CheckBox,在第一次簽入原始碼時沒有用,但是,在以後你提交代碼的時候是非常有用的。

點擊OK按鈕,會彈出下面的表單,要求輸入憑據:

在上面的表單中輸入使用者名稱和密碼,點擊OK按鈕:

如所示,好了,原始碼已經成功匯入SVN伺服器了。這時候團隊成員就可以從SVN伺服器上的匯出原始碼到自己的機器了。

2遷出原始碼到本機

就是從版本庫中取出某個目錄的拷貝到本機上某個目錄的操作,叫做CheckOut,這個操作是工作的基礎。

在本機建立檔案夾,右鍵點擊Checkout,彈出如的表單:

在中URL of Repository:下的文字框中輸入svn server中的程式碼程式庫的地址,其他預設,點擊OK按鈕,就開始遷出原始碼了。

說明:中的Checkout Depth,有4個選項,分別是遷出全部、只簽出下一級子目錄和檔案、只匯出檔案、只簽出空項目,預設的是第一項。上面的例子中,我們也可以使用web的方式存取碼庫,在瀏覽器中輸入http://zt.net.henu.edu.cn/svn/StartKit/

這時候也會彈出對話方塊,要求輸入使用者名稱和密碼,通過驗證後即可瀏覽程式碼程式庫中的內容。

開啟目錄,可以看到如的檔案夾結構:

一旦你對檔案或檔案夾做了任何修改,那麼檔案或檔案夾的顯示圖片機會發生變化。中我修改了其中的二個檔案:

看一下不同狀態所對應的圖片:

3.提交修改過的檔案到SVN伺服器

例如,修改了位於Model檔案中的二個檔案ImageInfo.cs和NewsInfo.cs

注意:提交原始碼到伺服器時,一定確保原生代碼是最新版本,否則可能提交失敗,或者造成版本衝突。

在Model檔案夾上點擊右鍵或在Model檔案下的空白處點擊右鍵,點擊SVN Commit…彈出下面的表單:

點擊OK按鈕後,彈出如的表單:

commit的功能不僅僅是上傳,他會和伺服器上面的檔案進行對比,假如你更新了某個檔案而伺服器上面也有人更新了這個檔案,並且是在你checkout之後做的更新,那麼它會嘗試將你的更新和他人的更新進行融合(merge),假如自動 merge不成功,那麼報告conflict,你必須自己來手動merge,也就是把你的更新和別人的更新無衝突的寫在一起。commit的時候,最好填寫Log資訊,這樣保證別人可以看到你的更新究竟做了寫什麼。這就相當於上傳檔案並且說明自己做了那些修改,多人合作的時候log非常重要。

4.添加新檔案到SVN伺服器

假設我們在Model檔案下添加一個新的類檔案UserInfo.cs,在檔案UserInfo.cs上點擊右鍵,點擊TortoiseSVN=>>Add,彈出如的表單:

選中UserInfo.cs檔案,點擊OK按鈕,這樣並沒有將這個檔案提交到SVN伺服器,只是將這個檔案標記為原始碼庫庫中的檔案,並將其狀態置為修改狀態。之後,我們要再SVN Commit這個檔案一次,才可以將其真正提交到SVN伺服器上的程式碼程式庫中。添加檔案夾的步驟也是一樣的。

5.更新機器碼與SVN伺服器上最新的版本一致

這個也很簡單,只要在需要更新的檔案夾上點擊右鍵或在該檔案下的空白處點擊右鍵,點擊SVN Update,就可以了。一般在提交修改之前,必須運行一下update操作來合并別人作出的新更改。

注意:更新操作可能會因為版本衝突而失敗,這是可以使用合并【Merge】或其他方法解決;也可能因為鎖定【Get Lock】而失敗,這是需要先解鎖【Release Lock】。 如果本地的代碼已經被修改,和commit一樣會先進行merge,不成功的話就會報告conflict 。另外需要注意的是,假如別人刪除了某個檔案,那麼更新之後你在本地的也會被刪除。

6.重新命名檔案或檔案夾,並將修改提交到SVN伺服器

只要在需要重新命名的檔案或檔案夾上點擊右鍵,點擊TortiseSVN=>Rename…,在彈出的表單中輸入新名稱,點擊OK按鈕,就可以了。此方法也不是直接重新命名,而是將該檔案或檔案夾的名稱標記為重新命名後名稱,也需要我們使用SVN Commit提交到SVN伺服器後才真正重新命名。

7.刪除檔案或檔案夾,並將修改提交到SVN伺服器

最簡單就是,你直接刪除檔案或檔案夾,然後使用SVN Commit提交更新到SVN伺服器。另外一種方法是在你要刪除的檔案或檔案夾上點擊右鍵=>>TortoiseSVN=>> Delete刪除,此方法也不是直接刪除,而是將該檔案或檔案夾的狀態置為刪除,也需要我們使用SVN Commit提交到SVN伺服器後才真正刪除。

8. 如何在同一個在一個工程的各個分支或者主幹之間切換
使用tortoise SVN—>switch ,在URL中輸入branch或trunk的url地址。

9.比較兩個版本之間的差別

· 如果你想看到你的本機複本有哪些更加,只用在資源管理員中右鍵菜單下選TortoiseSVN→ 比較差異。

· 如果你想查看主幹程式(假如你在分支上開發)有哪些修改或者是某一分支(假如你在主幹上開發)有哪些修改,你可以使用右鍵菜單。在你點擊檔案的同時按住Shift鍵,然後選擇TortoiseSVN→ URL比較。在彈出的對話方塊中,將特別顯示將與你本地版本做比較的版本的URL地址。

10.  如何為一個SVN主工程建立分支或tag

分支的基本概念:開發的一條線獨立於另一條線,如果回顧曆史,可以發現兩條線分享共同的曆史,一個分支總是從一個備份開始的,從那裡開始,發展自己專屬的曆史。

SVN分支的管理實際上就是把不同的分支用不同的檔案儲存,因此你在取得新版本的時候會發現,不同分支的最新檔案也會被擷取下來。建立tag操作,相當於把當前的代碼版本複製一份到其他地方,然後以這個地方為出發點進行新的開發,與原來位置的版本互不干擾。

· 選擇你要產生分支的檔案,點擊滑鼠右鍵,選擇[分支/標記...]

· 在[至URL(T)]輸入框中將檔案重新命名為你的分支檔案名稱,輸入便於區分的日誌資訊,點擊確認。

· 在SVN倉庫中會複製一個你所指定的檔案,檔案名稱就是你所命名的,但是在你的本地目錄上看不到建立的分支檔案名稱,要使你的檔案更新作用到你的分支上,你必須選擇檔案,點擊滑鼠右鍵,選擇[切換...],選擇你重新命名的檔案,點擊確定即可。這樣你的本地檔案就和分支檔案關聯上了,不要奇怪,這時本地目錄上看到的檔案名稱仍然為舊的檔案名稱。

11.衝突解決

當檔案發生衝突時,SVN會額外建立3個不受版本控制的檔案,同時被衝突檔案如果能夠合并,會在被衝突檔案內部留下衝突記錄。例如,衝突的檔案為plugin.c,BASE版本是1458,HEAD為1459,會產生3個臨時檔案plugin.c.mine,plugin.c.r1458,plugin.c.r1459,

解決思路:A. 手動修改被衝突檔案 B. 放棄自己的更改。實際中,解決辦法很靈活,一般需要與他人商量

注意:由於這3個檔案是在Update後才建立的,而Update之後,工作拷貝的BASE目錄已經變成更新後的版本了,所以放棄自己的更改會回到新版本。如果不是用Revert的方法解決衝突的話,由於那3個臨時檔案留在那裡,會使Subversion認為衝突沒有解決,所以要運行resolved告訴SVN衝突解決或者刪除臨時檔案。

三、Linux下SVN用戶端的使用:

1.Checkout:

文法:checkout(co) URL[@REV]... [PATH]

可以指明Checkout的版本號碼,預設CheckOut操作是針對HEAD版本進行的,大多數情況下我們需要HEAD版本,但如果需要曆史版本,可以用-r(--revision)參數或者是用“@版本號碼”的形式

例:

· … -r 1452 會檢出1452版,如果存在的話

· … -r {“2007-05-05”} 會檢出最接近這個日期的版本

· …/trunk@1452 效果同第1個例子

遞迴與不遞迴,-N:不遞迴(僅針對頂層目錄),否則目錄遞迴(預設,常用)

· 例1:svn co svn://218.94.9.38/svnrepos/skizcorp/trunk     在目前的目錄建立一個trunk目錄,裡面是工作拷貝

· 例2:svn co svn://localhost/torm I:/PROJECTS/torm   會在I:/PROJECTS/目錄下建立torm目錄,裡面存放工作拷貝

2.Update:

文法: update(up) [PATH...]

把版本庫的修改同步到本地的過程是Update。

· 例1:up 直接把工作拷貝更新到最新版(HEAD版)

· 例2:up -r 2007 更新到2007版

· 例3:up doc/design 只更新doc/design下的檔案

-r和-N參數仍然有用

Update會修改被更新目錄的BASE版本號碼。某個檔案的BASE版本是指存放在管理目錄.svn中的該檔案拷貝的版本,Revert會使該檔案回到BASE版本

做Update操作時,SVN會列印出受影響檔案的狀態,有以下幾種:

· A Added

· D Deleted

· U Updated

· C Conflict

· G Merged

注意:若提示C,表示衝突,衝突可以用status命令加-u參數來預測

3.Revert:

Revert是指放棄對某個檔案的修改,把該檔案的內容回複和BASE版本相同,也就是,把該檔案的狀態回複到未修改狀態

文法:revert 檔案/路徑

例子:

· 例1 revert abc.c 丟棄對abc.c的所有修改

· 例2 revert src/edu/nju/pojo 放棄對此目錄下所有檔案的修改

四、注意事項:

1.實際上,從你把原始碼遷簽入SVN伺服器開始,每一個版本的資料和檔案,就算是你已經刪除了的,也都可以隨時遷出。

2.向SVN伺服器提交原始碼的時候,一定不要提交bin、obj 等檔案夾,否則會很麻煩。但是web項目的bin目錄除外,但是web項目的bin目錄中的引用其他項目而產生的dll不需要提交。

3.對於第三方庫或程式集,不要簡單從他們的安裝位置引用,而是在你的解決方案下,添加一個Library的目錄,把需要的程式集或者庫檔案複製到這裡,然後從Library目錄引用。

4.關於checkout和export的區別,當你要發布或編譯的時候,最好採用export,它不會引入svn的附加檔案,這樣檔案結構顯得比較乾淨。而當你需要修改和提交的時候,用checkout,它會在你本地建立一個工作區,Checkout到某處的代碼,將會被 TortoiseSVN監視,裡面的檔案可以享受各種SVN的服務。

5.假如你需要給帶有綠色對勾檔案改名或者移動它的位置,請不要使用windows的功能,右鍵點擊它們,TortoiseSVN都有相應的操作。想象這些檔案已經不在是你本地的東西,你的一舉一動都必須讓Tortoise知道:

· 把一個檔案加入SVN版本控制,用add命令

· 從版本控制中移除,用delete(rm, remove)命令

· 移動或者重新命名,用move(rename)命令

· 拷貝,用copy命令

· 建立目錄,用mkdir命令

· ……

6.假如修改了某個檔案但是你後悔了,可以右鍵點擊它選擇Revert,它將變回上次checkout時候的情況,或者Revert整個工程到任意一個從前的版本。

7.使用Commit時注意: 如有多個檔案需要同時提交,同時檔案在不同的目錄下,必須找到這些檔案的最上層目錄上點擊 Commit,TortoiseSVN會搜尋被點擊目錄以及該目錄下所有的檔案,並將修改變動的檔案羅列在列表中。 仔細查看列表中的檔案,確定哪些檔案時需要更新的,如果不需要更新某個已經變化了的檔案,只需要在該檔案上點擊右鍵,選擇還原作業;如遇到檔案衝突(衝突:要提交的檔案已被其他人改動並提交到版本庫中)要啟用解決衝突功能。

8.對於branches、tags、trunk這三個目錄,並不是subversion必需的,而是被總結的一種良好的團隊開發習慣,其使用方法為:

· 開發人員提交所有的新特性到主幹。 每日的修改提交到/trunk:新特性,bug修正和其他。

· 這個主幹被拷貝到“發布”分支。 當小組認為軟體已經做好發布的準備(如,版本1.0)然後/trunk會被拷貝到/branches/1.0。

· 項目組繼續並行工作,一個小組開始對分支進行嚴酷的測試,同時另一個小組在/trunk繼續新的工作(如,準備2.0),如果一個bug在任何一個位置被發現,錯誤修正需要來回運送。然而這個過程有時候也會結束,例如分支已經為發布前的最終測試“停滯”了。

· 分支已經作了標籤並且發布,當測試結束,/branches/1.0作為引用快照已經拷貝到/tags/1.0.0,這個標籤被打包發布給客戶。

· 分支多次維護。當繼續在/trunk上為版本2.0工作,bug修正繼續從/trunk運送到/branches/1.0,如果積累了足夠的 bug修正,管理部門決定發布1.0.1版本:拷貝/branches/1.0到/tags/1.0.1,標籤被打包發布。

· 一般建立最初的repository時,就建好這三個目錄,把所有代碼放入/trunk中,如:要將project1目錄下的代碼匯入 repository,project1的結構就是:project1/branches,project1/tags,project1 /trunk,project1/trunk/food.c,project1/trunk/egg.pc……,然後將project1目錄匯入 repository,建立最初的資料庫。然後export回project1,作為本地工作目錄。

9.檢驗修改:

· 通過status命令可以檢查工作拷貝的狀態

· 通過diff命令可以檢查更改的內容

10. 關於SVN的開發模式(轉載)

Subversion有一個很標準的目錄結構,是這樣的。
比如項目是proj,svn地址為svn://proj/,那麼標準的svn布局是

svn://proj/ | +-trunk +-branches +-tags

這是一個標準的布局,trunk為主開發目錄,branches為分支開發目錄,tags為tag存檔目錄(不允許修改)。但是具體這幾個目錄應該如何使用,svn並沒有明確的規範,更多的還是使用者自己的習慣。
對於這幾個開發目錄,一般的使用方法有兩種。我更多的是從軟體產品的角度出發(比如freebsd),因為互連網的開發模式是完全不一樣的。
第一種方法,使用trunk作為主要的開發目錄。
一般的,我們的所有的開發都是基於trunk進行開發,當一個版本/release開發告一段落(開發、測試、文檔、製作安裝程式、打包等)結束後,代碼處於凍結狀態(人為規定,可以通過hook來進行管理)。此時應該基於當前凍結的程式碼程式庫,打tag。當下一個版本/階段的開發工作單位開始,繼續在trunk進行開發。
此時,如果發現了上一個已發行版本(Released Version)有一些bug,或者一些很急迫的功能要求,而正在開發的版本(Developing Version)無法滿足時間要求,這時候就需要在上一個版本上進行修改了。應該基於發行版對應的tag,做相應的分支(branch)進行開發。
例如,剛剛發布1.0,正在開發2.0,此時要在1.0的基礎上進行bug修正。
按照時間的順序

1. 1.0開發完畢,程式碼凍結

2. 基於已經凍結的trunk,為release1.0打tag
此時的目錄結構為
svn://proj/
             +trunk/  (freeze)
             +branches/
             +tags/
                     +tag_release_1.0 (copy from trunk)

3. 2.0開始開發,trunk此時為2.0的開發版

4. 發現1.0有bug,需要修改,基於1.0的tag做branch
此時的目錄結構為
svn://proj/
             +trunk/  ( dev 2.0 )
             +branches/
                           +dev_1.0_bugfix (copy from tag/release_1.0)
             +tags/
                     +release_1.0 (copy from trunk)

5. 在1.0 bugfix branch進行1.0 bugfix開發,在trunk進行2.0開發

6. 在1.0 bugfix 完成之後,基於dev_1.0_bugfix的branch做release等

7. 根據需要選擇性的把dev_1.0_bugfix這個分支merge回trunk(什麼時候進行這步操作,要根據具體情況)

這是一種很標準的開發模式,很多的公司都是採用這種模式進行開發的。trunk永遠是開發的主要目錄。
第二種方法,在每一個release的branch中進行各自的開發,trunk只做發布使用。
這種開發模式當中,trunk是不承擔具體開發工作單位的,一個版本/階段的開發工作單位在開始的時候,根據已經release的版本做新的開發分支,並且基於這個分支進行開發。還是舉上面的例子,這裡面的時序關係是。

1. 1.0開發,做dev1.0的branch
此時的目錄結構
svn://proj/
             +trunk/  (不擔負開發工作單位 )
             +branches/
                           +dev_1.0 (copy from trunk)
             +tags/

2. 1.0開發完成,merge dev1.0到trunk
此時的目錄結構
svn://proj/
             +trunk/  (merge from branch dev_1.0)
             +branches/
                           +dev_1.0 (開發工作單位結束,freeze)
             +tags/

3. 根據trunk做1.0的tag
此時的目錄結構
svn://proj/
             +trunk/  (merge from branch dev_1.0)
             +branches/
                           +dev_1.0 (開發工作單位結束,freeze)
             +tags/
                     +tag_release_1.0 (copy from trunk)

4. 1.0開發,做dev2.0分支
此時的目錄結構
svn://proj/
             +trunk/ 
             +branches/
                           +dev_1.0 (開發工作單位結束,freeze)
                           +dev_2.0 (進行2.0開發)
             +tags/
                     +tag_release_1.0 (copy from trunk)

5. 1.0有bug,直接在dev1.0的分支上修複
此時的目錄結構
svn://proj/
             +trunk/ 
             +branches/
                           +dev_1.0 (1.0bugfix)
                           +dev_2.0 (進行2.0開發)
             +tags/
                     +tag_release_1.0 (copy from trunk)

6. 選擇性的進行代碼merge

這其實是一種分散式的開發,當各個部分相對獨立一些(功能性的),可以開多個dev的分支進行開發,這樣各人/組都不會相互影響。比如dev_2.0_search和dev_2.0_cache等。但是這樣merge起來就是一個很痛苦的事情。
這裡要注意一下的,第六步進行選擇性的merge,是可以當2.0開發結束後一起把dev_1.0(bugfix用)和dev_2.0(新版本開發用)merge回trunk。或者先把dev_1.0 merge到dev_2.0,進行測試等之後再merge回trunk。
這兩種方法各有利弊,第一種方法是可以得到一個比較純的dev_2.0的開發分支,而第二種方法則更加的保險,因為要測試嘛。
以上呢,就是我說的兩種開發模式了,具體哪種好,並沒有定論。這裡大致的說一下各自的優缺點
第一種開發模式(trunk進行主要開發,集中式):
優點:管理簡單
缺點:當開發的模組比較多,開發人數/小團隊比較多的時候,很容易產生衝突而影響對方的開發。因為所有的改動都有可能觸碰對方的改動
第二重開發模式(分支進行主要開發,分散式):
優點:各自開發獨立,不容易相互影響。
缺點:管理複雜,merge的時候很麻煩,容易死人。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.