SVN 基本操作
檢出checkout(co)
svn co ${url}
更新update(up)
svn up
送出commit(ci)
svn ci -m " 修改xxx 問題"
檢視目前目錄最近5 次送出記錄
svn log -l 5
檢視目前工作拷貝資訊
svn info
檢視目前未送出的檔案status(st)
svn st
這個指令輸出每個添加、修改、删除過的目錄和檔案,前面的C 表示沖突,要特别注意。linux 下也可以用svn st | grep ^C 來檢視沖突項。
檢視目前修改内容
svn diff
撤銷目前修改,覆寫為資源庫最新版本
svn revert path/filename
遞歸撤銷目前目錄修改,覆寫為資源庫最新版本。注意新加的檔案不會被删除,這時也可以删除工作拷貝,重新checkout
svn revert . --recursive
SVN merge
自動合并
主幹到分支
建立分支以後,一個要做的事情就是定期将主幹上的修改合并到分支。先進入分支的工作拷貝,确認分支上所有修改已經送出,然後:
$ svn merge http://codeserver/calc/trunk
--- Merging r345 through r356 into '. ':
U button.c
U integer.c
--- Recording mergeinfo for merge of r345 through r356 into '. ':
U .
$
假設t1 時刻建立了分支,t2 時刻執行上面的指令進行合并,t3 時刻再次執行上面的指令進行合并。 由于分支是從主幹分離出去的,是以第一次合并的時候(t2 ),svn 能知道分支建立以後進行了哪些修改,它會将分支建立以後這段時間主幹的修改(t1 ~t2 ),應用到目前工作拷貝。
第二次執行上述指令的時候,svn 會意識到t1 ~t2 時刻的修改已經合并過了,是以它僅将t2 ~t3 時間段内主幹的修改,應用到目前工作拷貝。 第二次合并的時候,svn 能夠做到智能合并,這依賴于svn:mergeinfo 屬性,請注意上面指令輸出的最後一行,表示svn 正在将svn:mergeinfo 屬性記錄到目前目錄下,是以執行svn merge 目錄的時候,最好在工作拷貝的根路徑下執行。
svn:mergeinfo 的内容大緻如下,它記錄合并了哪個路徑的哪兩個版本的差異,可用svn propget svn:mergeinfo path 檢視,輸出類似如下:
/branches/V8822_optimiz_20090722/lottery:8828-9374
/branches/V8865_wap_20090727/lottery:8876-8937
/branches/V8944_P3_20090803/lottery:8992-9400
/branches/V9377_newp3_20090818/lottery:9400-9947
/branches/V9377_wappay_20090818/lottery:9404-9493
分支回主幹
在分支上開發完成後,需要将分支合并到主幹。進入主幹的工作拷貝的根目錄,運作
$ svn merge http://codeserver/calc/branchurl --reintegrate
我們假設上述指令發生在t4 時刻,如果上面的指令不帶--reintegrate 參數,可能會造成沖突,在svn 看來,t1 時刻建立了分支,然後主幹上進 行了一些修改,分支上也進行了一些同樣的修改(原因是我們在t2 、t3 時刻曾經将主幹的修改合并到分支),是以就沖突了。 加上這個參數以後,根據分支目錄http://codeserver/calc/branchurl 上的svn:mergeinfo 資訊,svn 在進行合 并的時候會排除主幹遷移到分支的這些修改,僅僅将分支上的修改遷回主幹。
假設在t5 時刻,需要再次合并分支上的修改,這時可以不帶--reintegrate 參數,因為在t4 時刻執行指令以後,已經将svn :mergeinfo 記錄在主幹。
手工合并
svn merge 可以了解為比較資源庫中的兩個不同版本(diff ),然後将差異應用到目前工作拷貝。 實際上,上面描述的自動合并功能是svn1.5 以後才有的,在這之前都是通過手工合并的方式工作。同時,在一些比較複雜的場景,手工合并會更加靈活。手工合并的方式為:
$ svn merge -r version1:version2 http://codeserver/calc/branchurl
$ svn merge -c version1 http://codeserver/calc/branchurl
上面的version1 和version2 是版本号,可以用HEAD 來代替目前最新版本。第一條指令将分支上version1 到version2 的修改合并到目前工作副本,第二條指令将第version1 次送出的修改合并到目前工作副本。
特别要注意了解 變更集 的概念。下面以15 選5 項目的分支為例,假設svn log 如下(經過簡化)。
------------------------------------------------------------------------
r24673 | yeli.hl | 2012-01-08 21:44:33 +0800 ( 日, 08 1 2012) | 1 line
開獎時間修改為20 :30
------------------------------------------------------------------------
r24644 | yeli.hl | 2012-01-06 11:42:22 +0800 ( 五, 06 1 2012) | 1 line
修正參與連結
------------------------------------------------------------------------
r24615 | yeli.hl | 2012-01-04 18:59:30 +0800 ( 三, 04 1 2012) | 1 line
merge trunk 24611
------------------------------------------------------------------------
r24601 | yeli.hl | 2012-01-04 15:29:43 +0800 ( 三, 04 1 2012) | 1 line
優化追号期數的顯示
------------------------------------------------------------------------
r24585 | yeli.hl | 2012-01-04 13:55:42 +0800 ( 三, 04 1 2012) | 1 line
修改“ 我的淘寶” 導覽列為3.1 版本。
------------------------------------------------------------------------
r24506 | yeli.hl | 2011-12-30 15:17:26 +0800 ( 五, 30 12 2011) | 1 line
merge trunk 24505
------------------------------------------------------------------------
r24182 | yeli.hl | 2011-12-14 18:01:48 +0800 ( 三, 14 12 2011) | 1 line
十五選五中獎号碼解析。
------------------------------------------------------------------------
r24050 | yeli.hl | 2011-12-05 15:04:39 +0800 ( 一, 05 12 2011) | 1 line
取彩期的時間程式排程。15X5 重命名。投注頁面靜态代碼拆分。
------------------------------------------------------------------------
r23950 | yeli.hl | 2011-11-28 16:50:16 +0800 ( 一, 28 11 2011) | 1 line
anhui 15*5
可以看到,建立分支的那一次送出是r23950 ,則-r 23950:24050 和-c 24050 代表的是同一個 變更集 ,前者表示23950 ~24050 的差異,後者表示24050 這次送出的變更,其實它們都是一樣的,都是24050 這次送出導緻的變更。是以,假設我們已 經合并了-r A:B ,如果B 之後又有一系列送出,最新版本是C ,我們想把這之後所有的修改并過來,則需要-r B:C ,注意第二次包括了B 。
假設現在我們想要手動方式把這個分支的變更遷回主幹。則指令為(需要排除兩次merge 主幹的修改):
$ svn merge -r 23950:24182 branch_url
$ svn merge -r 24506:24601 branch_url
$ svn merge -r 24615:HEAD branch_url
如果用-c 方式,最後一個指令等效為:
$ svn merge -c 24644 branch_url
$ svn merge -c 24673 branch_url
撤銷已送出操作(復原)
merge 的另外一個用途是撤銷已經送出的代碼,具體的做法是反向merge ,用下面的指令撤銷一次送出,假設url 路徑上進行了不應該的送出,進入該路徑的工作拷貝,執行
$ svn merge -c -A url
$ svn merge -r C:B url
第一個指令撤銷版本号是A 的送出,注意版本号前面的減号。第二個指令撤銷B ~C 的送出。執行完以後,再commit 。 當然,實際上svn 并不能删除任意一個版本,這些操作仍然都會在曆史中,它的作用隻是在目前的HEAD 中撤銷了某次(或某段)送出的内容。
注意事項
1. 為了防止造成破壞,可以帶上--dry-run 參數進行預覽,合并的時候如果帶上這個參數,工作拷貝将不會被修改,但是你能夠看見有哪些代碼被修改,哪些有沖突。
2. merge 前保證所有代碼已經送出,并且已經進行了更新,并檢查目前的工作拷貝是正确的。
3. 執行merge 操作以後,解決完沖突立即送出。這樣可以保證本次送出代表了一次純粹的merge 。例如上面的r24506 、r24615 ,在手工merge 回主幹的時候,需要排除這些送出,如果這些送出包含了其它修改就沒有辦法區分了。
4. 送出的注釋中描述清楚目前是從哪個版本merge 到哪個版本,有時候手工合并的時候需要參考到。
5. 在根目錄執行merge 操作,避免在子目錄和檔案中留下mergeinfo 資訊。
彩票SVN 相關操作
建立代碼分支
以lottery 為例,随便找個目錄,執行類似下面的指令
svn cp http://svn.taobao-develop.com/repos/lottery/trunk/lottery \
http://svn.taobao-develop.com/repos/lottery/branches/V${ 目前主幹版本号}_${ 項目名稱}_${date}/lottery \
-m " 建立XXX 項目分支" --parents
可以到http://svn.taobao-develop.com/repos/lottery/branches/ 下參考其它的分支命名。
合并主幹的最新修改到分支
開發一段時間以後,需要将主幹的最新修改合并到項目分支。進入分支工作拷貝的根路徑(請注意一定要在根路徑進行操作),運作
1. svn info 确認目前工作路徑正确:指向分支
2. svn st 确認所有代碼都已經送出
3. 運作指令
4. svn merge http://svn.taobao-develop.com/repos/lottery/trunk/lottery
5. 人肉解決沖突,可以用svn st 檢視(*nix 下用svn st | grep ^C 檢視) 是否有沖突,C 開頭的檔案辨別有沖突,解決完以後用svn resolved path/filename 标記沖突為已解決
6. svn st 确認已經沒有沖突了
7. 送出
合并分支修改到主幹
上日常的時候,需要将項目分支修改合并到日常伺服器的主幹工作拷貝,但是不送出。在主幹工作拷貝根路徑(請注意一定要在根路徑進行操作)下執行以下操作
1. svn info 确認目前工作路徑正确:指向主幹
2. svn st 确認所有代碼都已經送出
3. 運作指令
4. svn merge http://svn.taobao-develop.com/repos/lottery/branches/V${ 目前主幹版本号}_${ 項目名稱}_${date}/lottery --reintegrate
5. 人肉解決沖突,可以用svn st 檢視(*nix 下用svn st | grep ^C 檢視) 是否有沖突,C 開頭的檔案辨別有沖突,解決完以後用svn resolved path/filename 标記沖突為已解決
6. svn st 确認已經沒有沖突了
删除代碼分支(項目預發後删除代碼分支)
随便找個目錄,執行下面的指令(lottery 和keno 沒有差別)
svn mv http://svn.taobao-develop.com/repos/lottery/branches/V${ 目前主幹版本号}_${ 項目名稱}_${date}/lottery \
http://svn.taobao-develop.com/repos/lottery/branches/backup_branches/V${ 目前主幹版本号}_${ 項目名稱}_${date}/lottery \
-m " 删除${ 項目名稱} 代碼分支"
項目合并
可先從主幹拉一個分支,兩個項目分别将自己的修改合并到這個分支。上日常的時候再将這個分支合并到主幹。