基本的工作循環
Subversion有許多特性、選項和華而不實的高級功能,但日常的工作中你只使用其中的一小部分,在這一節里,我們會介紹許多你在日常工作中常用的命令。
典型的工作周期是這樣的:
- 更新你的工作拷貝
- 做出修改
- svn add
- svn delete
- svn copy
- svn move
- 檢驗修改
- 可能會取消一些修改
- 解決沖突(合并別人的修改)
- 提交你的修改
更新你的工作副本
當你在一個團隊的項目里工作時,你希望更新你的工作拷貝得到所有其他人這段時間作出的修改,使用svn update讓你的工作拷貝與最新的版本同步。
$ svn update
U foo.c
U bar.c
Updated to revision 2.
這種情況下,其他人在你上次更新之后提交了對foo.c和bar.c的修改,因此Subversion更新你的工作拷貝來引入這些更改。
當服務器通過svn update將修改傳遞到你的工作拷貝時,每一個項目之前會有一個字母,來讓你知道Subversion為保持最新對你的工作拷貝作了哪些工作。關于這些字母的詳細含義,可以看svn update。
修改你的工作副本
現在你可以開始工作并且修改你的工作拷貝了,你很容易決定作出一個修改(或者是一組),像寫一個新的特性,修正一個錯誤等等。這時可以使用的Subversion命令包括svn add、 svn delete、svn copy和svn move。如果你只是修改版本庫中已經存在的文件,在你提交之前,不必使用上面的任何一個命令。
你可以對工作拷貝做出兩種修改:文件修改和目錄樹修改。你不需要告訴Subversion你希望修改一個文件,只需要用你的編輯 器、字處理器、圖形程序或任何工具做出修改,Subversion自動監測到文件的更改,此外,二進制文件的處理方式和文本文件一樣—也有同樣的效率。對 于目錄樹更改,你可以告訴Subversion將文件和目錄預定的刪除、添加、拷貝或移動標記,這些動作會在工作拷貝上立刻發生效果,但只有提交后才會在 版本庫里生效。
下面是Subversion用來修改目錄樹結構的五個子命令。
版本控制符號連接
在非Windows平臺,Subversion可以將特殊類型符號鏈接(或是“symlink”)版本化,一個符號鏈接是對文件系統中其他對象的透明引用,可以通過對符合鏈接操作實現對引用對象的讀寫操作。
當符號鏈提交到Subversion版本庫,Subversion會記住這個文件實際上是一個符號鏈,也會知道這個符號鏈指向的“對象”。 當這個符號鏈檢出到另一個支持符號鏈的操作系統上時,Subversion會重新構建文件系統級的符號鏈接。當然這樣不會影響在Windows這類不支持 符號鏈的系統上,在此類系統上,Subversion只會創建一個包含指向對象路徑的文本文件,因為這個文件不能在Windows系統上作為符號鏈使用, 所以它也會防止Windows用戶作其他Subversion相關的操作。
svn add foo
預定將文件、目錄或者符號鏈foo添加到版本庫,當你下次提交后,foo會成為其父目錄的一個子對象。注意,如果foo是目錄,所有foo中的內容也會預定添加進去,如果你只想添加foo本身,請使用--non-recursive (-N)參數。
svn delete foo
預定將文件、目錄或者符號鏈foo從版本庫中刪除,如果foo是文件,它馬上從工作拷貝中刪除,如果是目錄,不會被刪除,但是Subversion準備好刪除了,當你提交你的修改,foo就會在你的工作拷貝和版本庫中被刪除。[4]
svn copy foo bar
建立一個新的項目bar作為foo的復制品,會自動預定將bar添加,當在下次提交時會將bar添加到版本庫,這種拷貝歷史會記錄下來(按照來自foo的方式記錄),svn copy并不建立中介目錄。
svn move foo bar
這個命令與與運行svn copy foo bar;svn delete foo完全相同,bar作為foo的拷貝準備添加,foo已經預定被刪除,svn move不建立中介的目錄。
svn mkdir blort
這個命令同運行 mkdir blort; svn add blort相同,也就是創建一個叫做blort的文件,并且預定添加到版本庫。
不通過工作副本修改版本庫
有一些情況下會立刻提交目錄樹的修改到版本庫,這只發生在子命令直接操作URL,而不是工作拷貝路徑時。以特定的方式使用svn mkdir、svn copy、svn move和svn delete可以針對URL操作(并且不要忘記svn import只針對URL操作)。
指定URL的操作方式有一些區別,因為在使用工作拷貝的運作方式時,工作拷貝成為一個“集結地”,可以在提交之前整理組織所要做的修改,直接對URL操作就沒有這種奢侈,所以當你直接操作URL的時候,所有以上的動作代表一個立即的提交。
檢查你的修改
當你完成修改,你需要提交他們到版本庫,但是在此之前,檢查一下做過什么修改是個好主意,通過提交前的檢查,你可以整理一份精確的日志信息,你也可以發現你不小心修改的文件,給了你一次恢復修改的機會。此外,這是一個審查和仔細察看修改的好機會,你可通過命令svn status瀏覽所做的修改,通過svn diff檢查修改的詳細信息。
看!沒有網絡!
這三個命令(svn status、svn diff和svn revert)都可以在沒有網絡的情況下工作(假定你的版本庫是通過網絡而不是本地訪問的),這讓你在沒有網絡連接時的管理修改過程更加容易,像在飛機上旅行,乘坐火車往返或是在海灘上奮力工作時。[5]
Subversion通過在.svn管理區域使用原始的版本緩存來做到這一點,這使得報告和恢復本地修改而不必訪問網絡,這個緩存(叫做“text-base”)也允許Subversion可以根據原始版本生成一個壓縮的增量(“區別”) 提交—即使你有個非常快的網絡,有這樣一個緩存有極大的好處,只向服務器提交修改的部分而不是整個文件。
Subversion已經被優化來幫助你完成這個任務,可以在不與版本庫通訊的情況下做許多事情,詳細來說,對于每一個文件,你的的工作拷貝在.svn包含了一個“原始的”拷貝,所以Subversion可以快速的告訴你那些文件修改了,甚至允許你在不與版本庫通訊的情況下恢復修改。
查看你的修改概況
為了瀏覽修改的內容,你會使用這個svn status命令,在所有Subversion命令里,svn status可能會是你用的最多的命令。
CVS 用戶:控制另類的更新!
你也許使用cvs update來看你做了哪些修改,svn status會給你所有你做的改變—而不需要訪問版本庫,并且不會在不知情的情況下與其他用戶作的更改比較。
在Subversion,update只是做這件事—將工作拷貝更新到版本庫的最新版本,你可以消除使用update察看本地修改的習慣。
如果你在工作拷貝的頂級目錄運行不帶參數的svn status命令,它會檢測你做的所有的文件或目錄的修改,以下的例子是來展示svn status可能返回的狀態碼(注意,#之后的不是svn status打印的)。
A stuff/loot/bloo.h # file is scheduled for addition
C stuff/loot/lump.c # file has textual conflicts from an update
D stuff/fish.c # file is scheduled for deletion
M bar.c # the content in bar.c has local modifications
在這種格式下,svn status打印6列字符,緊跟一些空格,接著是文件或者目錄名。第一列告訴一個文件或目錄的狀態或它的內容,返回代碼如下:
A item
預定加入到版本庫的文件、目錄或符號鏈的item。
C item
文件item發生沖突,在從服務器更新時與本地版本發生交迭,在你提交到版本庫前,必須手工的解決沖突。
D item
文件、目錄或是符號鏈item預定從版本庫中刪除。
M item
文件item的內容被修改了。
如果你傳遞一個路徑給svn status,它只給你這個項目的信息:
$ svn status stuff/fish.c
D stuff/fish.c
svn status也有一個--verbose (-v)選項,它可以顯示工作拷貝中的所有項目,即使沒有改變過的:
$ svn status -v
M 44 23 sally README
44 30 sally INSTALL
M 44 20 harry bar.c
44 18 ira stuff
44 35 harry stuff/trout.c
D 44 19 ira stuff/fish.c
44 21 sally stuff/things
A 0 ? ? stuff/things/bloo.h
44 36 harry stuff/things/gloo.c
這是svn status的“加長形式”,第一列保持相同,第二列顯示一個工作版本號,第三和第四列顯示最后一次修改的版本號和修改人(這些列不會與我們剛才提到的字符混淆)。
上面所有的svn status調用并沒有聯系版本庫,只是與.svn中的原始數據進行比較的結果,最后,是--show-updates (-u)選項,它將會聯系版本庫為已經過時的數據添加新信息:
$ svn status -u -v
M * 44 23 sally README
M 44 20 harry bar.c
* 44 35 harry stuff/trout.c
D 44 19 ira stuff/fish.c
A 0 ? ? stuff/things/bloo.h
Status against revision: 46
注意這兩個星號:如果你現在執行svn update,你的README和trout.c會被更新,這告訴你許多有用的信息—你可以在提交之前,需要使用更新操作得到文件README的更新,或者說文件已經過時,版本庫會拒絕了你的提交。(后面還有更多關于此主題)。
關于文件和目錄,svn status可以比我們的展示顯示更多的內容,完整的描述可以看svn status。
檢查你的本地修改的詳情
另一種檢查修改的方式是svn diff命令,你可以通過不帶參數的svn diff精確的找出你所做的修改,這會輸出統一區別格式的區別信息:
$ svn diff
Index: bar.c
===================================================================
--- bar.c (revision 3)
+++ bar.c (working copy)
@@ -1,7 +1,12 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <stdio.h>
int main(void) {
- printf("Sixty-four slices of American Cheese...\n");
+ printf("Sixty-five slices of American Cheese...\n");
return 0;
}
Index: README
===================================================================
--- README (revision 3)
+++ README (working copy)
@@ -193,3 +193,4 @@
+Note to self: pick up laundry.
Index: stuff/fish.c
===================================================================
--- stuff/fish.c (revision 1)
+++ stuff/fish.c (working copy)
-Welcome to the file known as 'fish'.
-Information on fish will be here soon.
Index: stuff/things/bloo.h
===================================================================
--- stuff/things/bloo.h (revision 8)
+++ stuff/things/bloo.h (working copy)
+Here is a new file to describe
+things about bloo.
svn diff命令通過比較你的文件和.svn的“原始”文件來輸出信息,預定要增加的文件會顯示所有增加的文本,要刪除的文件會顯示所有要刪除的文本。
輸出的格式為統一區別格式(unified diff format),刪除的行前面加一個-,添加的行前面有一個+,svn diff命令也打印文件名和打補丁需要的信息,所以你可以通過重定向一個區別文件來生成“補丁”:
$ svn diff > patchfile
舉個例子,你可以把補丁文件發送郵件到其他開發者,在提交之前審核和測試。
Subversion使用內置區別引擎,缺省情況下輸出為統一區別格式。如果你期望不同的輸出格式,你可以使用--diff-cmd指定外置的區別程序,并且通過--extensions傳遞其他參數,舉個例子,察看本地文件foo.c的區別,同時忽略大小寫差異,你可以運行svn diff --diff-cmd /usr/bin/diff --extensions '-bc' foo.c。
取消本地修改
假定我們在看svn diff的輸出,你發現對某個文件的所有修改都是錯誤的,或許你根本不應該修改這個文件,或者是從開頭重新修改會更加容易。
這是使用svn revert的好機會:
$ svn revert README
Reverted 'README'
Subversion把文件恢復到未修改的狀態,叫做.svn目錄的“原始”拷貝,應該知道svn revert可以恢復任何預定要做的操作,舉個例子,你不再想添加一個文件:
$ svn status foo
? foo
$ svn add foo
A foo
$ svn revert foo
Reverted 'foo'
$ svn status foo
? foo
注意
svn revertITEM的效果與刪除ITEM然后執行svn update -r BASEITEM完全一樣,但是,如果你使用svn revert它不必通知版本庫就可以恢復文件。
或許你不小心刪除了一個文件:
$ svn status README
README
$ svn delete README
D README
$ svn revert README
Reverted 'README'
$ svn status README
README
解決沖突(合并別人的修改)
我們可以使用svn status -u來預測沖突,當你運行svn update一些有趣的事情發生了:
$ svn update
U INSTALL
G README
C bar.c
Updated to revision 46.
U和G沒必要關心,文件干凈的接受了版本庫的變化,文件標示為U表明本地沒有修改,文件已經根據版本庫更新。G標示合并,標示本地已經修改過,與版本庫沒有重迭的地方,已經合并。
但是C表示沖突,說明服務器上的改動同你的改動沖突了,你需要自己手工去解決。
當沖突發生了,有三件事可以幫助你注意到這種情況和解決問題:
- Subversion在更新時打印C標記,并且標記這個文件已沖突。
- 如果Subversion認為這個文件是可合并的,它會置入沖突標記—特殊的橫線分開沖突的“兩面”—在文件里可視化的描述重疊的部分(Subversion使用svn:mime-type屬性來決定一個文件是否可以使用上下文的,以行為基礎的合并,更多信息可以看“文件內容類型”一節。)
- 對于每一個沖突的文件,Subversion放置三個額外的未版本化文件到你的工作拷貝:
filename.mine
你更新前的文件,沒有沖突標志,只是你最新更改的內容。(如果Subversion認為這個文件不可以合并,.mine文件不會創建,因為它和工作文件相同。)
filename.rOLDREV
這是你的做更新操作以前的BASE版本文件,就是你在上次更新之后未作更改的版本。
filename.rNEWREV
這是你的Subversion客戶端從服務器剛剛收到的版本,這個文件對應版本庫的HEAD版本。
這里OLDREV是你的.svn目錄中的修訂版本號,NEWREV是版本庫中HEAD的版本號。
舉一個例子,Sally修改了sandwich.txt,Harry剛剛改變了他的本地拷貝中的這個文件并且提交到服務器,Sally在提交之前更新它的工作拷貝得到了沖突:
$ svn update
C sandwich.txt
Updated to revision 2.
$ ls -1
sandwich.txt
sandwich.txt.mine
sandwich.txt.r1
sandwich.txt.r2
在這種情況下,Subversion不會允許你提交sandwich.txt,直到你的三個臨時文件被刪掉。
$ svn commit -m "Add a few more things"
svn: Commit failed (details follow):
svn: Aborting commit: '/home/sally/svn-work/sandwich.txt' remains in conflict
如果你遇到沖突,三件事你可以選擇:
- “手動”合并沖突文本(檢查和修改文件中的沖突標志)。
- 用某一個臨時文件覆蓋你的工作文件。
- 運行svn revert <filename>來放棄所有的本地修改。
一旦你解決了沖突,你需要通過命令svn resolved讓Subversion知道,這樣就會刪除三個臨時文件,Subversion就不會認為這個文件是在沖突狀態了。[6]
$ svn resolved sandwich.txt
Resolved conflicted state of 'sandwich.txt'
手工合并沖突
第一次嘗試解決沖突讓人感覺很害怕,但經過一點訓練,它簡單的像是騎著車子下坡。
這里一個簡單的例子,由于不良的交流,你和同事Sally,同時編輯了sandwich.txt。Sally提交了修改,當你準備更新你的工作拷貝,沖突發生了,我們不得不去修改sandwich.txt來解決這個問題。首先,看一下這個文件:
$ cat sandwich.txt
Top piece of bread
Mayonnaise
Lettuce
Tomato
Provolone
<<<<<<< .mine
Salami
Mortadella
Prosciutto
=======
Sauerkraut
Grilled Chicken
>>>>>>> .r2
Creole Mustard
Bottom piece of bread
小于號、等于號和大于號串是沖突標記,并不是沖突的數據,你一定要確定這些內容在下次提交之前得到刪除,前兩組標志中間的內容是你在沖突區所做的修改:
<<<<<<< .mine
Salami
Mortadella
Prosciutto
=======
后兩組之間的是Sally提交的修改沖突:
=======
Sauerkraut
Grilled Chicken
>>>>>>> .r2
通常你并不希望只是刪除沖突標志和Sally的修改—當她收到三明治時,會非常的吃驚。所以你應該走到她的辦公室或是拿起電話告訴Sally,你沒辦法從從意大利熟食店得到想要的泡菜。[7]一旦你們確認了提交內容后,修改文件并且刪除沖突標志。
Top piece of bread
Mayonnaise
Lettuce
Tomato
Provolone
Salami
Mortadella
Prosciutto
Creole Mustard
Bottom piece of bread
現在運行svn resolved,你已經準備好提交了:
$ svn resolved sandwich.txt
$ svn commit -m "Go ahead and use my sandwich, discarding Sally's edits."
現在我們準備好提交修改了,注意svn resolved不像我們本章學過的其他命令一樣需要參數,在任何你認為解決了沖突的時候,只需要小心運行svn resolved,—一旦刪除了臨時文件,Subversion會讓你提交這文件,即使文件中還存在沖突標記。
記住,如果你修改沖突時感到混亂,你可以參考subversion生成的三個文件—包括你未作更新的文件。你也可以使用三方交互合并工具檢驗這三個文件。
復制文件到你的工作文件
如果你只是希望取消你的修改,你可以僅僅拷貝Subversion為你生成的文件替換你的工作拷貝:
$ svn update
C sandwich.txt
Updated to revision 2.
$ ls sandwich.*
sandwich.txt sandwich.txt.mine sandwich.txt.r2 sandwich.txt.r1
$ cp sandwich.txt.r2 sandwich.txt
$ svn resolved sandwich.txt
腳注:使用svn revert
如果你得到沖突,經過檢查你決定取消自己的修改并且重新編輯,你可以恢復你的修改:
$ svn revert sandwich.txt
Reverted 'sandwich.txt'
$ ls sandwich.*
sandwich.txt
注意,當你恢復一個沖突的文件時,不需要再運行svn resolved。
提交你的修改
最后!你的修改結束了,你合并了服務器上所有的修改,你準備好提交修改到版本庫。
svn commit命令發送所有的修改到版本庫,當你提交修改時,你需要提供一些描述修改的日志信息,你的信息會附到這個修訂版本上,如果信息很簡短,你可以在命令行中使用--message(或-m)選項:
$ svn commit -m "Corrected number of cheese slices."
Sending sandwich.txt
Transmitting file data .
Committed revision 3.
然而,如果你把寫日志信息當作工作的一部分,你也許會希望告訴Subversion通過一個文件名得到日志信息,使用--file選項:
$ svn commit -F logmsg
Sending sandwich.txt
Transmitting file data .
Committed revision 4.
如果你沒有指定--message或者--file選項,Subversion會自動地啟動你最喜歡的編輯器(見“配置”一節的editor-cmd部分)來編輯日志信息。
提示
如果你使用編輯器撰寫日志信息時希望取消提交,你可以直接關掉編輯器,不要保存,如果你已經做過保存,只要簡單的刪掉所有的文本并再次保存,然后退出。
$ svn commit
Waiting for Emacs...Done
Log message unchanged or not specified
a)bort, c)ontinue, e)dit
a
$
版本庫不知道也不關心你的修改作為一個整體是否有意義,它只檢查是否有其他人修改了同一個文件,如果別人已經這樣做了,你的整個提交會失敗,并且提示你一個或多個文件已經過時了:
$ svn commit -m "Add another rule"
Sending rules.txt
svn: Commit failed (details follow):
svn: Your file or directory 'sandwich.txt' is probably out-of-date
…
(錯誤信息的精確措辭依賴于網絡協議和你使用的服務器,但對于所有的情況,其思想完全一樣。)
此刻,你需要運行svn update來處理所有的合并和沖突,然后再嘗試提交。
我們已經覆蓋了Subversion基本的工作周期,還有許多其它特性可以管理你得版本庫和工作拷貝,但是只使用前面介紹的命令你就可以很進行日常工作了,我們還會覆蓋更多用的還算頻繁的命令。
[4] 當然沒有任何東西是在版本庫里被刪除了—只是在版本庫的HEAD里消失了,你可以通過檢出(或者更新你的工作拷貝)你做出刪除操作的前一個修訂版本來找回所有的東西,詳細請見“找回刪除的項目”一節。
[5] 而且你也沒有WAN卡,考慮到你得到我們,哈!
[6] 你也可以手工的刪除這三個臨時文件,但是當Subversion會給你做時你會自己去做嗎?我們是這樣想的。
[7] 如果你向他們詢問,他們非常有理由把你帶到城外的鐵軌上。
檢驗歷史
你的版本庫就像是一臺時間機器,它記錄了所有提交的修改,允許你檢查文件或目錄以及相關元數據的歷史。通過一個Subversion命令你可以根據時間或修訂號取出一個過去的版本(或者恢復現在的工作拷貝),然而,有時候我們只是想看看歷史而不想回到歷史。
有許多命令可以為你提供版本庫歷史:
svn log
展示給你主要信息:每個版本附加在版本上的作者與日期信息和所有路徑修改。
svn diff
顯示特定修改的行級詳細信息。
svn cat
取得在特定版本的某一個文件顯示在當前屏幕。
svn list
顯示一個目錄在某一版本存在的文件。
產生歷史修改列表
找出一個文件或目錄的歷史信息,使用svn log命令,svn log將會提供你一條記錄,包括:誰對文件或目錄作了修改、哪個修訂版本作了修改、修訂版本的日期和時間、還有如果你當時提供了日志信息,也會顯示。
$ 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
------------------------------------------------------------------------
注意日志信息缺省根據時間逆序排列,如果希望察看特定順序的一段修訂版本或者單一版本,使用--revision(-r) 選項:
$ 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
…
這樣只會顯示這個工作文件(或者URL)做過修訂的版本的日志信息。
如果你希望得到目錄和文件更多的信息,你可以對svn log命令使用--verbose (-v)開關,因為Subversion允許移動和復制文件和目錄,所以跟蹤路徑修改非常重要,在詳細模式下,svn log 輸出中會包括一個路徑修改的歷史:
$ svn log -r 8 -v
------------------------------------------------------------------------
r8 | sally | 2002-07-14 08:15:29 -0500 | 1 line
Changed paths:
M /trunk/code/foo.c
M /trunk/code/bar.h
A /trunk/code/doc/README
Frozzled the sub-space winch.
------------------------------------------------------------------------
svn log也有一個--quiet (-q)選項,會禁止日志信息的主要部分,當與--verbose結合使用,僅會顯示修改的文件名。
為什么svn log給我一個空的回應?
當使用Subversion一些時間后,許多用戶會遇到這種情況:
$ svn log -r 2
------------------------------------------------------------------------
$
乍一看,好像是一個錯誤,但是想一下修訂版本號是作用在版本庫整體之上的,如果你沒有提供路徑,svn log會使用當前目錄作為默認的目標,所以,作為結果,如果你對一個本身和子目錄在指定版本到現在沒有做過修改的目錄運行這個命令,你會得到空的日志。如果你希望察看某個版本做的修改的日志,只需要直接告訴svn log使用版本庫頂級的目錄作為參數,例如svn log -r 2 http://svn.collab.net/repos/svn。
檢查歷史修改的詳情
我們已經看過svn diff—使用標準區別文件格式顯示區別,它在提交前用來顯示本地工作拷貝與版本庫的區別。
事實上,svn diff有三種不同的用法:
- 檢查本地修改
- 比較工作拷貝與版本庫
- 比較版本庫與版本庫
比較本地修改
像我們看到的,不使用任何參數調用時,svn diff將會比較你的工作文件與緩存在.svn的“原始”拷貝:
$ svn diff
Index: rules.txt
===================================================================
--- rules.txt (revision 3)
+++ rules.txt (working copy)
@@ -1,4 +1,5 @@
Be kind to others
Freedom = Responsibility
Everything in moderation
-Chew with your mouth open
+Chew with your mouth closed
+Listen when others are speaking
$
比較工作拷貝和版本庫
如果傳遞一個--revision(-r)參數,你的工作拷貝會與指定的版本比較。
$ svn diff -r 3 rules.txt
Index: rules.txt
===================================================================
--- rules.txt (revision 3)
+++ rules.txt (working copy)
@@ -1,4 +1,5 @@
Be kind to others
Freedom = Responsibility
Everything in moderation
-Chew with your mouth open
+Chew with your mouth closed
+Listen when others are speaking
$
比較版本庫與版本庫
如果通過--revision (-r)傳遞兩個通過冒號分開的版本號,這兩個版本會進行比較。
$ svn diff -r 2:3 rules.txt
Index: rules.txt
===================================================================
--- rules.txt (revision 2)
+++ rules.txt (revision 3)
@@ -1,4 +1,4 @@
Be kind to others
-Freedom = Chocolate Ice Cream
+Freedom = Responsibility
Everything in moderation
Chew with your mouth open
$
與前一個修訂版本比較更方便的辦法是使用--change (-c):
$ svn diff -c 3 rules.txt
Index: rules.txt
===================================================================
--- rules.txt (revision 2)
+++ rules.txt (revision 3)
@@ -1,4 +1,4 @@
Be kind to others
-Freedom = Chocolate Ice Cream
+Freedom = Responsibility
Everything in moderation
Chew with your mouth open
$
最后,即使你在本機沒有工作拷貝,還是可以比較版本庫的修訂版本,只需要在命令行中輸入合適的URL:
$ svn diff -c 5 http://svn.example.com/repos/example/trunk/text/rules.txt
…
$
瀏覽版本庫
通過svn cat和svn list,你可以在未修改工作修訂版本的情況下查看文件和目錄的內容,實際上,你甚至也不需要有一個工作拷貝。
svn cat
如果你只是希望檢查一個過去的版本而不希望察看它們的區別,使用svn cat:
$ svn cat -r 2 rules.txt
Be kind to others
Freedom = Chocolate Ice Cream
Everything in moderation
Chew with your mouth open
$
你可以重定向輸出到一個文件:
$ svn cat -r 2 rules.txt > rules.txt.v2
$
svn list
svn list可以在不下載文件到本地目錄的情況下來察看目錄中的文件:
$ svn list http://svn.collab.net/repos/svn
README
branches/
clients/
tags/
trunk/
如果你希望察看詳細信息,你可以使用--verbose(-v) 參數:
$ svn list -v http://svn.collab.net/repos/svn
20620 harry 1084 Jul 13 2006 README
23339 harry Feb 04 01:40 branches/
21282 sally Aug 27 09:41 developer-resources/
23198 harry Jan 23 17:17 tags/
23351 sally Feb 05 13:26 trunk/
這些列告訴你文件和目錄最后修改的修訂版本、做出修改的用戶、如果是文件還會有文件的大小,最后是修改日期和項目的名字。
警告
沒有任何參數的svn list命令缺省使用當前工作拷貝的版本庫URL,而不是本地工作拷貝的目錄。畢竟,如果你希望列出本地目錄,你只需要使用ls(或任何合理的非UNIX等價物)。
獲得舊的版本庫快照
除了以上的命令,你可以使用帶參數--revision的svn update和svn checkout來使整個工作拷貝“回到過去”[8]:
$ svn checkout -r 1729 # Checks out a new working copy at r1729
…
$ svn update -r 1729 # Updates an existing working copy to r1729
…
提示
許多Subversion新手使用前面的svn update實例來“回退”修改,但是你不能提交修改,你獲得有新修訂版本的過時工作拷貝也是沒有用的。關于如何“回退”,我們可以看“找回刪除的項目”一節。
最后,如果你構建了一個版本,并且希望從Subversion打包文件,但是你不希望有討厭的.svn目錄,這時你可以導出版本庫的一部分文件而沒有.svn目錄。就像svn update和svn checkout,你也可以傳遞--revision選項給svn export:
$ svn export http://svn.example.com/svn/repos1 # Exports latest revision
…
$ svn export http://svn.example.com/svn/repos1 -r 1729
# Exports revision r1729
…
[8] 看到了吧?我們說過Subversion是一個時間機器。