------------------ 參考文檔 --------------------
官方文檔: http://www.subversion.org.cn/svnbook/ 包括可下載的PDF 和一頁HTML。
配置文檔: 去ubuntu的wiki吧~~ 如果用 svn + ssh 的話,基本不用配置,按下面“快速工作”即可。
------------------ 快速工作: -------------------
1. 建立版本庫:
我的方式,是用svn+ssh來訪問版本庫,這意味著:
不用啟動svnserve守護進程,而是由每次ssh連接到版本庫時,自動啟動svnserve,工作完再退出svnserve進程。這些東西,都是本地的svn調用ssh讓它那樣做的。而啟動的svnserve進程的身份就是ssh用戶的身份,而ssh用戶來自于系統用戶,這就是這種方法的優點:就用系統用戶了。
正因為如此,每個用戶是否對版本庫能讀寫,就依賴于版本庫的權限設置,就是你用svnadmin create生成的文件的權限設置。
我的策略是,為了讓某些用戶讀寫版本庫,我創建了一個svn用戶,和一個svn組,然后在/home/svn下建立版本庫。然后把所有需要訪問svn的用戶,加到svn組中,并設置版本庫的所有文件,svn組的人都能夠讀寫。
在版本庫機器上,具體如下:
adduser svn # 創建svn用戶和svn組
gpasswd -a fengyi svn # 把fengyi用戶加到svn組
svnadmin create /home/svn/buptnic # 創建版本庫buptnic
chmod -R g+w /home/svn/buptnic # 讓所有的文件為組可寫(因為默認一般是組可讀了)
以上兩步,也可以改為,先用umask 0002,再用svnadmin 一樣的效果。因為默認的umask一般是0022,這會去掉組的寫權限。
注意:一旦svnadmin create之后,其他的事情,就應該用svn在工作拷貝機器上做了。———— 要點是,大部分svn的子命令,最終效果都是操作版本庫,但是分兩種途徑。如果子命令帶URL的,一般對版本庫直接操作,如果不帶URL的,一般是先對工作拷貝進行操作,然后用commit使版本庫生效。當然,好多命令,即可以帶URL,也可以不帶,一般都是先update,再更改工作拷貝,再commit。
在工作拷貝機器上,具體如下:
svn mkdir svn+ssh://svn@210.25.137.252/home/svn/buptnic/flow # 建立flow項目目錄
svn mkdir svn+ssh://svn@210.25.137.252/home/svn/buptnic/flow/trunk # 建立flow/trunk目錄
svn mkdir svn+ssh://svn@210.25.137.252/home/svn/buptnic/flow/branches # 建立flow/branches目錄
svn mkdir svn+ssh://svn@210.25.137.252/home/svn/buptnic/flow/tags # 建立flow/tags目錄
svn import /home/echo/src svn+ssh://svn@210.25.137.252/home/svn/buptnic/flow/trunk # 將本地的src下的源文件導入到版本庫的trunk目錄下。注意,trunk是主分支,一般習慣是放任何東西,包括文檔,第三方庫。
然后,就OK了,你可以找個地方,用fengyi用戶做checkout了。
svn checkout svn+ssh://fengyi@210.25.137.252/home/svn/buptnic/flow
注意的是:版本庫中,雖然你通過mkdir建立了那些目錄,上傳了那些文件,但是,你是在/home/svn/buptnic/flow中直接看不到的,它們都放在flow 下的db目錄中,是虛擬文件系統里。
2. 用戶基本操作原則:
(1) 不管是 版本庫 還是 工作拷貝,他們的維護文件,都在他們的文件夾內,所以,如果要刪除他們,直接用文件系統的rm即可徹底刪除。
(2) 用svn子命令,對版本庫的直接操作,必須用一種形式的URL,而不能是普通文件路徑,包括在版本庫機器上!!!!!但是svnadmin等命令,就是直接用普通文件路徑來操作版本庫,并要求在版本庫機器上執行。
(3) 在工作拷貝的哪個目錄執行 svn 子命令,該命令的最后一個參數,默認就是當前目錄,這使得命令的效果從當前目錄開始作用。
這從每個目錄里有一個.svn看得出來,每個目錄都有維護文件,都可以單獨工作。這也是工作拷貝的不同部分允許不同版本號的基礎。
(4) commit只有當當前目錄下所有文件的版本號 等于 版本庫當前版本號時,才能成功。
工作拷貝的不同部分允許不同版本號,所以,當你commit時,可能當前目錄下,比如各個子目錄里 的版本號并不同,如果有比版本庫低的版本號,commit就不能成功,提示信息是 ... out of date ...,這時,你需要update一次,然后,再commit。當然,其他很多情形,也可能導致這種情況,最典型的就是(5)中文件沖突的情況。
(5) 先在工作拷貝上操作,然后commit到版本庫。
除了修改文件以外的任何操作,都用svn子命令完成,比如添加一個文件,創建之后,用svn add添加到本地拷貝。當你覺得本次的工作拷貝工作結束時,可以將其commit到版本庫,使得版本庫更新到新的revision。
(6) 解決沖突
解決沖突最好的辦法,就是兩個人不要編輯同一個文件。否則,見下面或資料,你就需要update一次,來合并兩人的文件(因為別人先commit了,版本庫里的版本號比自己的高,自己不會commit提交成功,需要先update)。如果需要手工解決沖突,見下面的解決辦法。
(7) 是的,如果兩個分支獨立發展太久,則必然改動較大,那merge是會有沖突的,你還是要手動解決。
merge和update沖突時,生成的沖突臨時文件名不同,但是源文件,都是被沖突標志標注了的,你只需要改源文件即可。里面<<<到>>>部分,是沖突區域,即svn認為,在這個區域上,兩個文件各自發展了自己的修改,所以第一個文件的修改,放到<<<和===中,第二文件的修改,放到===和>>>中,你自己選擇,保留哪個修改。如果某個修改為空,即如===和>>>中沒有代碼,那說明“修改”就是“刪除”操作。
所以,當我們把branches的文件merge到trunk時,得考慮清楚了,因為branches在修改bug,而trunk在增加新特性,為了把branches的bug修改通過merge引入trunk,是很可能導致沖突的。
(8) revert 和 merge
revert是在版本內恢復,即:當commit后,就是一個版本了,之后,如果更改了任何東西,但是還沒有commit的話,就可以恢復到上次commit后的狀態。revert不依靠版本庫,僅靠.svn目錄來維護信息。
而merge,則是依賴版本庫,做的則是版本間的差異比較,從而作用于某個目錄。使得內容恢復到某個版本狀態。
(9) 忘了的命令,用svn help subcmd 來查閱。
(10) diff, status, log 怎么用阿?
下面是trunk目錄下,svn status -v 的輸出:
28 28 fengyi .
28 26 fengyi sheep
28 26 fengyi sheep/sheep.c
28 20 svn main.c
28 28 fengyi cow
28 28 fengyi cow/main2.c
注意到:第一列是當前工作拷貝的版本號,是因為在trunk update后導致所有文件的版本號變為最新。但是,后面的一列數字,表明自那個版本號以來,文件沒有改過(不保證版本庫沒有更新)。你用svn log看那個文件,也只能看到那個號版本,看不到當前工作拷貝的版本號(沒改,沒commit,怎么可能有log!)
-------------------- 筆記 ---------------------
第一章 基本概念
svn就是能夠跟蹤數據變化的文件服務器
“拷貝-修改-合并”模型而不是“鎖定-修改-解鎖”(見保存的圖)
每當版本庫由用戶commit了一個提交,文件系統進入了一個新的狀態,叫做一次修訂(revision),每一個修訂版本被賦予一個獨一無二的自然數,commit顯然是原子操作。同時,可以看出,版本庫沒有回退的概念,只有工作拷貝有這個概念,版本庫只不過一直在往前走。
(許多其它版本控制系統使用每文件一個修訂號的策略,所以會感覺這些概念有點不一樣。)
SVN概念中,版本庫的修訂版本是統一的,就是說,任何時候,每個文件的“修訂版本”都是一樣的。
但是工作拷貝中經常是“混合修訂版本”,因為你只提交一個文件,導致版本庫中修訂版本加1,這時,你的工作拷貝中這個文件的修訂版本也加1,但是工作拷貝中其他的文件,只能維持原版本號,除非你update一次。
這是很有用的一個特性,它允許工作拷貝的任何一個部分在歷史中前進或后退。
svn有一個基本原則就是“推”動作不會導致“拉”,反之亦然。
svn commit & svn update 和 四種狀態 (是否修改+是否當前)
svn status --verbose 檢查“混合修訂版本”
svn log 顯示一個文件或目錄的歷史修改信息。
$ svn checkout http://svn.example.com:9834/repos
$ svn checkout file:///path/to/repos
$ svn checkout file://localhost/path/to/repos
C:\> svn checkout file:///X:/path/to/repos
$ svn checkout http://svn.example.com/repos/calc
$ svn commit button.c -m "Fixed a typo in button.c."
$ svn update
Subversion可以通過多種方式訪問版本庫!!
———— 一個重要意思是說:各種svn的子命令,都可以直接訪問版本庫。如果你在版本庫機器上,那么就用file:///,如果你在自己機器上,就用下面四種方式。
———— 但是,你怎么只操作本地的工作拷貝呢,以為你想在本地改,改完后再commit,那就不要加這些東西了,直接是文件名,或者不加就好。
模式 訪問方法
file:/// 直接版本庫訪問(本地磁盤)
http:// 通過配置Subversion的Apache服務器的WebDAV協議
https:// 與http://相似,但是包括SSL加密。
svn:// 通過svnserve服務自定義的協議
svn+ssh:// 與svn://相似,但通過SSH封裝。
但是注意:一般的做法,還是先update,merge,copy等命令把版本庫數據弄到工作拷貝,修改好工作拷貝后,再commit,這會導致版本庫的進入下一個revision。
如果直接在版本庫中操作的,比如copy,delete等,也會使得版本庫進入下一個reversion.
第二章 基本使用
svn help SUBCOMMAND
1. 創建版本庫
創建新的版本庫名 newrepos
$ svnadmin create /usr/local/svn/newrepos
將mytree下未版本化的文件,導入該版本庫,文件放在some/project下,沒有mytree文件夾了。
$ svn import mytree file:///usr/local/svn/newrepos/some/project -m "Initial import"
注意:import后的路徑,可以在版本庫上,也可以在自己機器上。一般,可以在自己機器上的代碼,直接這樣導入服務器上的版本庫。
列出newrepos版本庫中某文件夾下的文件。
$ svn list file:///usr/local/svn/newrepos/some/project
推薦的版本庫布局: 這里有paint和calc兩個項目
$ svn list file:///usr/local/svn/repos
/paint/trunk
/paint/branches
/paint/tags
/calc/trunk
/calc/branches
/calc/tags
/vender/vendorlib1/current #供方最新版本
/vender/vendorlib1/1.0 #上次最新版本的快照(svn copy)
注意:文件夾用 svn mkdir 創建。看你在版本庫主機上還是工作拷貝主機上,選用上面某一個URL可以對版本庫進行操作。
2. 初始化檢出
在本地創建一個工作拷貝,這個拷貝可能僅僅是一個版本庫中的一個文件夾。
$ svn checkout http://svn.collab.net/repos/svn/trunk
同上,只不過,在本地創建的是subv目錄,而不是trunk目錄。
$ svn checkout http://svn.collab.net/repos/svn/trunk subv
3. 基本的工作周期
更新你的工作拷貝
svn update
做出修改: 只有修改一個文件,可以直接修改,其他任何對文件和目錄的操作,均是先通過以下命令在工作拷貝生效,然后,你下次update的時候,才在版本庫生效。這種狀態,常見英文為: sth is scheduled for addition.(比如這個文件是add處理的)
svn add foo (先vim foo,然后用add命令添加)
svn delete foo (但是只有在update時,版本庫和工作拷貝內的刪除才會生效)
svn copy foo bar
svn move foo bar
svn mkdir foo (等于mkdir foo; snv add foo)
檢驗修改: 在你提交你的工作拷貝時,檢查一下修改了哪些東西是個好習慣,這不需要網絡(不需要和版本庫比對)
svn status (瀏覽所做的修改,傳說中用的最多的命令)
-v 顯示所有文件
-u 這個文件常用于預測update前的沖突。會聯系版本庫,看是否工作拷貝里,有過期的文件,以 * 標注。
可能的狀態碼為:
A # file is scheduled for addition
C # file has textual conflicts from an update
D # file is scheduled for deletion
M # the content in bar.c has local modifications
? # 這個文件還沒有版本化,你需要用svn add
svn diff (檢查修改的詳細信息,通過 svn diff > patchfile 可以生成補丁文件)
可能會取消一些修改
svn revert (任何修改,然后用revert就可以撤銷任何schedule 的操作,即上次update以來 schedule的操作)
解決沖突(合并別人的修改)
svn update (只要版本庫被別人修改,你鐵定不能commit,必須update一次,而update會嘗試合并被人修改過的版本庫和工作拷貝,生成新的工作拷貝,下面U表示更新(你沒有修改,但是版本庫被修改),G表示合并(你修改了,版本庫也修改了,兩者可以合并),C表示沖突(你修改了,版本庫修改了,兩者不能按照一定規則合并)。如果是C存在,那么你必須解決沖突,svn才能允許你下次commit。如果有沖突,那么對應bar.c 會有三個臨時文件被生成,它們是bar.c.mine, bar.c.rR1(你上次update時的文件), bar.c.rR2(版本庫中的最新版本號的文件)。這個三個臨時文件,會阻止你commit。此時的svn只是要求你考慮下更改沖突的文件,如果考慮好了,用svn resolved bar.c來告訴svn,你改好了,然后resolved會自動刪除這三個臨時文件,然后,你再commit,就行了!所以,svn只是要求你考慮清楚后,刪除這三個文件,它就可以commit了,不管你到底是不是真的改恰當了,這還是你的事,所以,如果不用svn resolved,而是直接刪除這三個文件,也是可以commit的。另外,這三個文件,可以用于你查閱,如果愿意的話。
更改沖突文件,通常可以:直接編輯沖突文件;用bar.c.rR2(R2 > R1)來替換bar.c;或者直接用svn revert來恢復文件到上次update時的狀態。如果是前面兩種方法,要接上svn resolved來告訴svn,沖突已解決好了,可以允許自己commit了。
$ svn update
U INSTALL
G README
C bar.c
Updated to revision 46.
svn resolved
提交你的修改
只有當你的工作拷貝的版本號=版本庫版本號時,才能提交成功!!!(小于就得先update,大于是不可能的)
svn commit -m "message"/ -F logfile
4. 檢驗歷史:
(1) svn log (從下面就看出每次 commit時 -m 的重要性了,對于追溯很重要)
$ svn log
------------------------------------------------------------------------
r3 | sally | Mon, 15 Jul 2002 18:03:46 -0500 | 1 line
Added include lines and corrected # of cheese slices.
------------------------------------------------------------------------
r2 | harry | Mon, 15 Jul 2002 17:47:57 -0500 | 1 line
Added main() methods.
------------------------------------------------------------------------
r1 | sally | Mon, 15 Jul 2002 17:40:08 -0500 | 1 line
Initial import
------------------------------------------------------------------------
$ svn log -r 5:19 # shows logs 5 through 19 in chronological order
$ svn log -r 19:5 # shows logs 5 through 19 in reverse order
$ svn log -r 8 # shows log for revision 8
$ svn log foo.c
$ svn log http://foo.com/svn/trunk/code/foo.c
注意:
a. 加上 -v 能顯示文件和目錄的移動和復制 等 “路徑修改” 信息,這可以用于找出刪除的項目。
b. 如果 svn log -r 8 沒有輸出信息,那請在后面跟出版本庫的路徑。
(2) svn diff
$ svn diff #比較工作拷貝和.svn中存的上次update時的版本。
$ svn diff -r 3 rules.txt #比較工作拷貝和版本庫3版
$ svn diff -r 2:3 rules.txt #比較版本庫的2版和3版。
(3) svn cat
$ svn cat -r 2 rules.txt #查看版本庫2版
(4) svn list
缺省列出的是當前工作拷貝對應的版本庫的URL下的東西,當然,你可以直接寫出版本庫。
$ svn list -v http://svn.collab.net/repos/svn
5. 時間機: ———— 注意:版本庫沒有回退的概念,只有你的工作拷貝有回退的概念!!
(1) 將工作拷貝,回退到以往某個版本: ———— 但注意,根據commit原理,這種回退的工作拷貝,你是無法commit的了。如果,你原意是想回退后,以后還能繼續提交,那應該用svn merge!!!!
$ svn checkout -r 1729 # Checks out a new working copy at r1729
$ svn update -r 1729 # Updates an existing working copy to r1729
(2) 將版本庫的1729版本打包。
$ svn export http://svn.example.com/svn/repos1 -r 1729
6. 清理:
status發現有L的,表明是鎖住了,這通常是由于svn上次要修改,所以鎖住,但是由于某種原因,進程退出了,所以鎖還在,這是用cleanup命令清除即可。
$ svn status
L somedir
M somedir/foo.c
$ svn cleanup
$ svn status
M somedir/foo.c
第三章 高級主題
1. 去掉未版本化的文件:
你當然不想讓臨時文件擾亂版本庫,也讓svn方法有svn自身提供的兩種方法,見這一章相應部分。我還是覺得復雜。
那就當svn add 和 import時,后面顯示指定出文件名,而不是默認讓它遞歸查找所有的文件和目錄。
2. 鎖定:
如果你想當你update后,就能鎖住某些版本庫的話。這樣使得一些非文本的對象,不會由于交替操作發生錯誤,如圖像處理。
3. 其他很多高級主題。
見章節中。
第四章 分支與合并
當你創建了一個版本庫時(svnadmin create),里面的目錄和文件可以用 svn copy 或者 svn move來移動。但不能在不同版本庫間移動。
1. 分支:
“分支”,沒有被SVN賦予特殊的意義,我們稱用 svn copy 后的新的目錄,為一個分支,但對于svn來講,只是一個普通目錄。
(1) 創建分支:
由于分支是對版本庫的操作,所以copy后的兩個參數都是版本庫URL,如果你在版本庫機器上,用file:///一樣。
$ svn copy http://svn.example.com/repos/calc/trunk \
http://svn.example.com/repos/calc/branches/my-calc-branch \
-m "Creating a private branch of /calc/trunk."
上面,也說明了分支放置的地方,在branches里,新建一個my-calc-branch。以后,也可以在branches里建立其他新的分支。
(2) 版本號還是往前走!
由于svn的一個版本庫內部沒有“分支”的內建概念,所以不管哪個“分支”被commit了,都會導致版本庫的版本號往前走。
2. 合并:
“合并”,即 svn merge 做的事,就是比較版本庫中兩個版本的區別,并把區別應用于你的工作拷貝。這沒有什么限制,兩個版本可以是任何兩個版本,你的工作拷貝,也可以是你本地的任何一個“分支”。但是,這個命令拿來干嘛呢?? 就是為了使得兩個“分支”能夠合并一些共同的東西,比如一個分支做了一些錯誤修改,另一個分支也應該跟著改。但是,這些修改是通過比較哪兩個版本,這就要靠你自己判斷了,一般是看別人用commit -m參數,提交的說明,比如它說,這次提交,修改了xxx,那你就可以比較這次提交和上次版本的差別,然后應用于自己的工作拷貝,這就是所謂的“合并”。
如果不能合并,不能合并的文件前,會打印C,就同update一樣。這往往表明,你選了錯誤的兩個版本作比較,使得差別不能應用于拷貝。這時,可用svn revert --recursive恢復修改。
另外,merge必須經常做,如果你打算維護兩個相關的分支的話。否則,長時間不做,merge起來,會沖突很多,不好解決。
下面是些用法:
$ svn merge -c 344 http://svn.example.com/repos/calc/trunk #默認合并到當前工作目錄
$ svn merge -c 344 http://svn.example.com/repos/calc/trunk my-calc-branch
$ svn merge http://svn.example.com/repos/branch1@150 \ #@后面接版本號
http://svn.example.com/repos/branch2@212 \
my-working-copy
$ svn merge -r 100:200 http://svn.example.com/repos/trunk my-working-copy
$ svn merge -r 100:200 http://svn.example.com/repos/trunk
不太懂 --ignore-ancestry 的用途,這個用于比較兩個不相關的目錄樹
3. 典型例子:
(1) 把某個branch合并到trunk
先進入工作拷貝里的trunk目錄,使得后面svn merge是針對這個工作拷貝。
$ cd calc/trunk
$ svn update
At revision 405.
用于merge的兩個版本庫版本,是my-calc-branch誕生時的版本341和目前的版本405。注意,這僅僅是對第一次merge,但是如果你后來又修改了分支,你還想merge,那顯然,從406到目前的版本即可。最新版本,可用HEAD代替。不知道,就看上面svn update,告訴你最新是405。或者用svn log查詢。
$ svn merge -r 341:405 http://svn.example.com/repos/calc/branches/my-calc-branch
U integer.c
U button.c
U Makefile
檢查一下狀態,不要有沖突的
$ svn status
M integer.c
M button.c
M Makefile
# ...examine the diffs, compile, test, etc...
然后提交,就可以完成合并到trunk。
$ svn commit -m "Merged my-calc-branch changes r341:405 into the trunk."
Sending integer.c
Sending button.c
Sending Makefile
Transmitting file data ...
Committed revision 406.
(2) 恢復工作拷貝到以前版本:
注意是303后面跟302,后面的小,這樣就能夠使得工作拷貝,回到以前的版本!! 這樣之后,是可以commit的,這不同于用checkout和update得到的以前版本,這種情況下無法commit.
$ svn merge -r 303:302 http://svn.example.com/repos/calc/trunk
U integer.c
$ svn status
M integer.c
$ svn diff
…
# verify that the change is removed
…
$ svn commit -m "Undoing change committed in r303."
Sending integer.c
Transmitting file data .
Committed revision 350.
(3) 恢復單個文件到以前版本:
如果你想對單個文件回溯? 那還是用svn copy把,它能夠直接把某個版本的文件拷貝到你當前的工作拷貝。如:
拷貝807版本的real.c到工作拷貝的當前目錄
$ svn copy -r 807 \
http://svn.example.com/repos/calc/trunk/real.c ./real.c
查看狀態
$ svn status
A + real.c
提交修改
$ svn commit -m "Resurrected real.c from revision 807, /calc/trunk/real.c."
Adding real.c
Transmitting file data .
Committed revision 1390.
(4) 當然,你可以選擇直接在版本庫中恢復文件和文件夾:
這所謂恢復,其實就是進入下一個revision,注意下面例子中revision號的變化。
比如你用這個刪除了:
$ svn delete http://svn.example.com/repos/calc/branches/my-calc-branch \
-m "Removing obsolete branch of calc project."
Committed revision 375.
你可以用這個來恢復:
$ svn copy -r 374 http://svn.example.com/repos/calc/branches/my-calc-branch \
http://svn.example.com/repos/calc/branches/my-calc-branch
Committed revision 376.
4. 常用分支模式:
大多數軟件存在這樣一個生命周期:編碼、測試、發布,然后重復。這樣有兩個問題,第一,開發者需要在質量保證小組測試假定穩定版本時繼續開發新特性,新工作在軟件測試時不可以中斷,第二,小組必須一直支持老的發布版本和軟件;如果一個bug在最新的代碼中發現,它一定也存在已發布的版本中,客戶希望立刻得到錯誤修正而不必等到新版本發布。
(1) 永久分支:
一般trunk做主分支(給開發者),branches做發布分支(給測試員測試,不允許添加特性,僅做bug修復),tag做打包分支(給用戶):
這是版本控制可以做的幫助,典型的過程如下:
* 開發者提交所有的新特性到主干。 每日的修改提交到/trunk:新特性,bug修正和其他。
* 這個主干被拷貝到“發布”分支。 當小組認為軟件已經做好發布的準備(如,版本1.0)然后/trunk會被拷貝到/branches/1.0。
* 項目組繼續并行工作,一個小組開始對分支進行嚴酷的測試(一般只允許做bug修復性的提交),同時另一個小組在/trunk繼續新的工作(如,添加新特性,準備2.0)。兩邊發現的bug,可以相互merge。注意,這種分支,也就是“維護某個版本”的由來。即不會添加新特性了,如果OK了,就放到tags里,然后以后有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,標簽被打包發布。
整個過程隨著軟件的成熟不斷重復:當2.0完成,一個新的2.0分支被創建,測試、打標簽和最終發布,經過許多年,版本庫結束了許多版本發布,進入了“維護”模式,許多標簽代表了最終的發布版本。
(2) 臨時分支:
有時,可能做些trunk的臨時分支,以開發某種特性,或做較大更改。
這些分支,一旦開發結束,就merge入主分支,并刪除自己。
(3) 供方分支:
顯然,我們需要用到別人提供的庫。但是,我們怎么用呢?一般是,放到我們的版本庫中,準備一個current目錄,將其放入,然后做快照到如1.0。然后拷貝到brunch中做使用和定制。然后,一旦有新版本發布,我們想用的話,把最新版本替換current,然后和1.0做比較,用merge將修改應用于brunch中的版本。
目錄結構為:
在repos根目錄下,再創建一個vender目錄,庫名叫libcomplex比如,就創建libcomplex目錄,在里面再創建current放最新版本,用1.0放上次版本的快照(svn copy)
-------- 從文檔上摘抄的例子:---------
也許一個例子有助于我們闡述這個算法,我們會使用這樣一個場景,我們的開發團隊正在開發一個計算器程序,與一個第三方的復雜數字運算庫libcomplex關聯。我們從供方分支的初始創建開始,并且導入供方drop,我們會把每株分支目錄叫做libcomplex,我們的代碼drop會進入到供方分支的子目錄current,并且因為svn import創建所有的需要的中間父目錄,我們可以使用一個命令完成這一步。
$ svn import /path/to/libcomplex-1.0 \
http://svn.example.com/repos/vendor/libcomplex/current \
-m 'importing initial 1.0 vendor drop'
…
我們現在在/vendor/libcomplex/current有了libcomplex當前版本的代碼,現在我們為那個版本作標簽(見“標簽”一節),然后拷貝它到主要開發分支,我們的拷貝會在calc項目目錄創建一個新的目錄libcomplex,它是這個我們將要進行自定義的供方數據的拷貝版本。
$ svn copy http://svn.example.com/repos/vendor/libcomplex/current \
http://svn.example.com/repos/vendor/libcomplex/1.0 \
-m 'tagging libcomplex-1.0'
…
$ svn copy http://svn.example.com/repos/vendor/libcomplex/1.0 \
http://svn.example.com/repos/calc/libcomplex \
-m 'bringing libcomplex-1.0 into the main branch'
…
我們取出我們項目的主分支—現在包括了第一個供方釋放的拷貝—我們開始自定義libcomplex的代碼,在我們知道之前,我們的libcomplex修改版本是已經與我們的計算器程序完全集成了。 [23]
幾周之后,libcomplex得開發者發布了一個新的版本—版本1.1—包括了我們很需要的一些特性和功能。我們很希望升級到這個版本,但不希望失去在當前版本所作的修改。我們本質上會希望把我們當前基線版本是的libcomplex1.0的拷貝替換為libcomplex 1.1,然后把前面自定義的修改應用到新的版本。但是實際上我們通過一個相反的方向解決這個問題,應用libcomplex從版本1.0到1.1的修改到我們修改的拷貝。
為了執行這個升級,我們取出一個我們供方分支的拷貝,替換current目錄為新的libcomplex 1.1的代碼,我們只是拷貝新文件到存在的文件上,或者是解壓縮libcomplex 1.1的打包文件到我們存在的文件和目錄。此時的目標是讓我們的current目錄只保留libcomplex 1.1的代碼,并且保證所有的代碼在版本控制之下,哦,我們希望在最小的版本控制歷史擾動下完成這件事。
完成了這個從1.0到1.1的代碼替換,svn status會顯示文件的本地修改,或許也包括了一些未版本化或者丟失的文件,如果我們做了我們應該做的事情,未版本化的文件應該都是libcomplex在1.1新引入的文件—我們運行svn add來將它們加入到版本控制。丟失的文件是存在于1.1但是不是在1.1,在這些路徑我們運行svn delete。最終一旦我們的current工作拷貝只是包括了libcomplex1.1的代碼,我們可以提交這些改變目錄和文件的修改。
我們的current分支現在保存了新的供方drop,我們為這個新的版本創建一個新的標簽(就像我們為1.0版本drop所作的),然后合并這從個標簽前一個版本的區別到主要開發分支。
$ cd working-copies/calc
$ svn merge http://svn.example.com/repos/vendor/libcomplex/1.0 \
http://svn.example.com/repos/vendor/libcomplex/current \
libcomplex
… # resolve all the conflicts between their changes and our changes
$ svn commit -m 'merging libcomplex-1.1 into the main branch'
…
5. 聰明的switch
svn switch可以把工作拷貝的全部或部分,邏輯上轉換為 其他分支 的工作拷貝! 這是繼前面,一個工作拷貝中可以混合不同版本后,又一種混合方式 ———— 混合不同的分支的部分。 它表現得像update!!
舉個例子,你的工作拷貝目錄是/calc/trunk,你已經做了很多修改,然后你突然發現應該在分支上修改更好,沒問題!你可以使用svn switch使得工作拷貝邏輯上變為分支的工作拷貝,而你本地修改還會保留,你可以測試并提交它們到分支。
如果服務器做了svn move造成文件移動,那么 svn update會?? 必須用svn switch??
6. 建立標簽:
標簽就是一次正式發行打包。這里再次說明了:標簽和分支一樣,都是人為的概念,對于svn來說,都是用svn copy制造的“快照”。比如標簽就是從trunk拷貝到tags,或者從測試的branch拷貝到tags。
但是,需要用一種方法,來禁止用戶提交commit,因為標簽概念上,不允許修改了,只是歷史沉淀。
怎么做呢??? svn+ssh的話,用基本文件系統的權限來解決吧。
http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/c2bb0245d00dd03786947321.html
只有注冊用戶登錄后才能發表評論。 | ||
![]() |
||
網站導航:
博客園
IT新聞
Chat2DB
C++博客
博問
管理
|
||
相關文章:
|
||