基本的工作循環(huán)
Subversion有許多特性、選項(xiàng)和華而不實(shí)的高級功能,但日常的工作中你只使用其中的一小部分,在這一節(jié)里,我們會介紹許多你在日常工作中常用的命令。
典型的工作周期是這樣的:
- 更新你的工作拷貝
- svn update
- 做出修改
- svn add
- svn delete
- svn copy
- svn move
- 檢驗(yàn)修改
- svn status
- svn diff
- 可能會取消一些修改
- svn revert
- 解決沖突(合并別人的修改)
- svn update
- svn resolved
- 提交你的修改
- svn commit
當(dāng)你在一個(gè)團(tuán)隊(duì)的項(xiàng)目里工作時(shí),你希望更新你的工作拷貝得到所有其他人這段時(shí)間作出的修改,使用svn update讓你的工作拷貝與最新的版本同步。
$ svn update
U foo.c
U bar.c
Updated to revision 2.
這種情況下,其他人在你上次更新之后提交了對foo.c和bar.c的修改,因此Subversion更新你的工作拷貝來引入這些更改。
當(dāng)服務(wù)器通過svn update將修改傳遞到你的工作拷貝時(shí),每一個(gè)項(xiàng)目之前會有一個(gè)字母,來讓你知道Subversion為保持最新對你的工作拷貝作了哪些工作。關(guān)于這些字母的詳細(xì)含義,可以看svn update。
現(xiàn)在你可以開始工作并且修改你的工作拷貝了,你很容易決定作出一個(gè)修改(或者是一組),像寫一個(gè)新的特性,修正一個(gè)錯(cuò)誤等等。這時(shí)可以使用的Subversion命令包括svn add、 svn delete、svn copy和svn move。如果你只是修改版本庫中已經(jīng)存在的文件,在你提交之前,不必使用上面的任何一個(gè)命令。
你可以對工作拷貝做出兩種修改:文件修改和目錄樹修改。你不需要告訴Subversion你希望修改一個(gè)文件,只需要用你的編輯 器、字處理器、圖形程序或任何工具做出修改,Subversion自動監(jiān)測到文件的更改,此外,二進(jìn)制文件的處理方式和文本文件一樣—也有同樣的效率。對 于目錄樹更改,你可以告訴Subversion將文件和目錄預(yù)定的刪除、添加、拷貝或移動標(biāo)記,這些動作會在工作拷貝上立刻發(fā)生效果,但只有提交后才會在 版本庫里生效。
下面是Subversion用來修改目錄樹結(jié)構(gòu)的五個(gè)子命令。
版本控制符號連接
在非Windows平臺,Subversion可以將特殊類型符號鏈接(或是“symlink”)版本化,一個(gè)符號鏈接是對文件系統(tǒng)中其他對象的透明引用,可以通過對符合鏈接操作實(shí)現(xiàn)對引用對象的讀寫操作。
當(dāng)符號鏈提交到Subversion版本庫,Subversion會記住這個(gè)文件實(shí)際上是一個(gè)符號鏈,也會知道這個(gè)符號鏈指向的“對象”。 當(dāng)這個(gè)符號鏈檢出到另一個(gè)支持符號鏈的操作系統(tǒng)上時(shí),Subversion會重新構(gòu)建文件系統(tǒng)級的符號鏈接。當(dāng)然這樣不會影響在Windows這類不支持 符號鏈的系統(tǒng)上,在此類系統(tǒng)上,Subversion只會創(chuàng)建一個(gè)包含指向?qū)ο舐窂降奈谋疚募驗(yàn)檫@個(gè)文件不能在Windows系統(tǒng)上作為符號鏈?zhǔn)褂茫?所以它也會防止Windows用戶作其他Subversion相關(guān)的操作。
svn add foo
預(yù)定將文件、目錄或者符號鏈foo添加到版本庫,當(dāng)你下次提交后,foo會成為其父目錄的一個(gè)子對象。注意,如果foo是目錄,所有foo中的內(nèi)容也會預(yù)定添加進(jìn)去,如果你只想添加foo本身,請使用--non-recursive (-N)參數(shù)。
svn delete foo
預(yù)定將文件、目錄或者符號鏈foo從版本庫中刪除,如果foo是文件,它馬上從工作拷貝中刪除,如果是目錄,不會被刪除,但是Subversion準(zhǔn)備好刪除了,當(dāng)你提交你的修改,foo就會在你的工作拷貝和版本庫中被刪除。[4]
svn copy foo bar
建立一個(gè)新的項(xiàng)目bar作為foo的復(fù)制品,會自動預(yù)定將bar添加,當(dāng)在下次提交時(shí)會將bar添加到版本庫,這種拷貝歷史會記錄下來(按照來自foo的方式記錄),svn copy并不建立中介目錄。
svn move foo bar
這個(gè)命令與與運(yùn)行svn copy foo bar;svn delete foo完全相同,bar作為foo的拷貝準(zhǔn)備添加,foo已經(jīng)預(yù)定被刪除,svn move不建立中介的目錄。
svn mkdir blort
這個(gè)命令同運(yùn)行 mkdir blort; svn add blort相同,也就是創(chuàng)建一個(gè)叫做blort的文件,并且預(yù)定添加到版本庫。
不通過工作副本修改版本庫
有一些情況下會立刻提交目錄樹的修改到版本庫,這只發(fā)生在子命令直接操作URL,而不是工作拷貝路徑時(shí)。以特定的方式使用svn mkdir、svn copy、svn move和svn delete可以針對URL操作(并且不要忘記svn import只針對URL操作)。
指定URL的操作方式有一些區(qū)別,因?yàn)樵谑褂霉ぷ骺截惖倪\(yùn)作方式時(shí),工作拷貝成為一個(gè)“集結(jié)地”,可以在提交之前整理組織所要做的修改,直接對URL操作就沒有這種奢侈,所以當(dāng)你直接操作URL的時(shí)候,所有以上的動作代表一個(gè)立即的提交。
當(dāng)你完成修改,你需要提交他們到版本庫,但是在此之前,檢查一下做過什么修改是個(gè)好主意,通過提交前的檢查,你可以整理一份精確的日志信息,你也可以發(fā)現(xiàn)你不小心修改的文件,給了你一次恢復(fù)修改的機(jī)會。此外,這是一個(gè)審查和仔細(xì)察看修改的好機(jī)會,你可通過命令svn status瀏覽所做的修改,通過svn diff檢查修改的詳細(xì)信息。
看!沒有網(wǎng)絡(luò)!
這三個(gè)命令(svn status、svn diff和svn revert)都可以在沒有網(wǎng)絡(luò)的情況下工作(假定你的版本庫是通過網(wǎng)絡(luò)而不是本地訪問的),這讓你在沒有網(wǎng)絡(luò)連接時(shí)的管理修改過程更加容易,像在飛機(jī)上旅行,乘坐火車往返或是在海灘上奮力工作時(shí)。[5]
Subversion通過在.svn管理區(qū)域使用原始的版本緩存來做到這一點(diǎn),這使得報(bào)告和恢復(fù)本地修改而不必訪問網(wǎng)絡(luò),這個(gè)緩存(叫做“text-base”)也允許Subversion可以根據(jù)原始版本生成一個(gè)壓縮的增量(“區(qū)別”) 提交—即使你有個(gè)非常快的網(wǎng)絡(luò),有這樣一個(gè)緩存有極大的好處,只向服務(wù)器提交修改的部分而不是整個(gè)文件。
Subversion已經(jīng)被優(yōu)化來幫助你完成這個(gè)任務(wù),可以在不與版本庫通訊的情況下做許多事情,詳細(xì)來說,對于每一個(gè)文件,你的的工作拷貝在.svn包含了一個(gè)“原始的”拷貝,所以Subversion可以快速的告訴你那些文件修改了,甚至允許你在不與版本庫通訊的情況下恢復(fù)修改。
為了瀏覽修改的內(nèi)容,你會使用這個(gè)svn status命令,在所有Subversion命令里,svn status可能會是你用的最多的命令。
CVS 用戶:控制另類的更新!
你也許使用cvs update來看你做了哪些修改,svn status會給你所有你做的改變—而不需要訪問版本庫,并且不會在不知情的情況下與其他用戶作的更改比較。
在Subversion,update只是做這件事—將工作拷貝更新到版本庫的最新版本,你可以消除使用update察看本地修改的習(xí)慣。
如果你在工作拷貝的頂級目錄運(yùn)行不帶參數(shù)的svn status命令,它會檢測你做的所有的文件或目錄的修改,以下的例子是來展示svn status可能返回的狀態(tài)碼(注意,#之后的不是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列字符,緊跟一些空格,接著是文件或者目錄名。第一列告訴一個(gè)文件或目錄的狀態(tài)或它的內(nèi)容,返回代碼如下:
A item
預(yù)定加入到版本庫的文件、目錄或符號鏈的item。
C item
文件item發(fā)生沖突,在從服務(wù)器更新時(shí)與本地版本發(fā)生交迭,在你提交到版本庫前,必須手工的解決沖突。
D item
文件、目錄或是符號鏈item預(yù)定從版本庫中刪除。
M item
文件item的內(nèi)容被修改了。
如果你傳遞一個(gè)路徑給svn status,它只給你這個(gè)項(xiàng)目的信息:
$ svn status stuff/fish.c
D stuff/fish.c
svn status也有一個(gè)--verbose (-v)選項(xiàng),它可以顯示工作拷貝中的所有項(xiàng)目,即使沒有改變過的:
$ 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的“加長形式”,第一列保持相同,第二列顯示一個(gè)工作版本號,第三和第四列顯示最后一次修改的版本號和修改人(這些列不會與我們剛才提到的字符混淆)。
上面所有的svn status調(diào)用并沒有聯(lián)系版本庫,只是與.svn中的原始數(shù)據(jù)進(jìn)行比較的結(jié)果,最后,是--show-updates (-u)選項(xiàng),它將會聯(lián)系版本庫為已經(jīng)過時(shí)的數(shù)據(jù)添加新信息:
$ 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
注意這兩個(gè)星號:如果你現(xiàn)在執(zhí)行svn update,你的README和trout.c會被更新,這告訴你許多有用的信息—你可以在提交之前,需要使用更新操作得到文件README的更新,或者說文件已經(jīng)過時(shí),版本庫會拒絕了你的提交。(后面還有更多關(guān)于此主題)。
關(guān)于文件和目錄,svn status可以比我們的展示顯示更多的內(nèi)容,完整的描述可以看svn status。
另一種檢查修改的方式是svn diff命令,你可以通過不帶參數(shù)的svn diff精確的找出你所做的修改,這會輸出統(tǒng)一區(qū)別格式的區(qū)別信息:
$ 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的“原始”文件來輸出信息,預(yù)定要增加的文件會顯示所有增加的文本,要刪除的文件會顯示所有要刪除的文本。
輸出的格式為統(tǒng)一區(qū)別格式(unified diff format),刪除的行前面加一個(gè)-,添加的行前面有一個(gè)+,svn diff命令也打印文件名和打補(bǔ)丁需要的信息,所以你可以通過重定向一個(gè)區(qū)別文件來生成“補(bǔ)丁”:
$ svn diff > patchfile
舉個(gè)例子,你可以把補(bǔ)丁文件發(fā)送郵件到其他開發(fā)者,在提交之前審核和測試。
Subversion使用內(nèi)置區(qū)別引擎,缺省情況下輸出為統(tǒng)一區(qū)別格式。如果你期望不同的輸出格式,你可以使用--diff-cmd指定外置的區(qū)別程序,并且通過--extensions傳遞其他參數(shù),舉個(gè)例子,察看本地文件foo.c的區(qū)別,同時(shí)忽略大小寫差異,你可以運(yùn)行svn diff --diff-cmd /usr/bin/diff --extensions '-bc' foo.c。
假定我們在看svn diff的輸出,你發(fā)現(xiàn)對某個(gè)文件的所有修改都是錯(cuò)誤的,或許你根本不應(yīng)該修改這個(gè)文件,或者是從開頭重新修改會更加容易。
這是使用svn revert的好機(jī)會:
$ svn revert README
Reverted 'README'
Subversion把文件恢復(fù)到未修改的狀態(tài),叫做.svn目錄的“原始”拷貝,應(yīng)該知道svn revert可以恢復(fù)任何預(yù)定要做的操作,舉個(gè)例子,你不再想添加一個(gè)文件:
$ svn status foo
? foo
$ svn add foo
A foo
$ svn revert foo
Reverted 'foo'
$ svn status foo
? foo
注意
svn revertITEM的效果與刪除ITEM然后執(zhí)行svn update -r BASEITEM完全一樣,但是,如果你使用svn revert它不必通知版本庫就可以恢復(fù)文件。
或許你不小心刪除了一個(gè)文件:
$ svn status README
README
$ svn delete README
D README
$ svn revert README
Reverted 'README'
$ svn status README
README
我們可以使用svn status -u來預(yù)測沖突,當(dāng)你運(yùn)行svn update一些有趣的事情發(fā)生了:
$ svn update
U INSTALL
G README
C bar.c
Updated to revision 46.
U和G沒必要關(guān)心,文件干凈的接受了版本庫的變化,文件標(biāo)示為U表明本地沒有修改,文件已經(jīng)根據(jù)版本庫更新。G標(biāo)示合并,標(biāo)示本地已經(jīng)修改過,與版本庫沒有重迭的地方,已經(jīng)合并。
但是C表示沖突,說明服務(wù)器上的改動同你的改動沖突了,你需要自己手工去解決。
當(dāng)沖突發(fā)生了,有三件事可以幫助你注意到這種情況和解決問題:
- Subversion在更新時(shí)打印C標(biāo)記,并且標(biāo)記這個(gè)文件已沖突。
- 如果Subversion認(rèn)為這個(gè)文件是可合并的,它會置入沖突標(biāo)記—特殊的橫線分開沖突的“兩面”—在文件里可視化的描述重疊的部分(Subversion使用svn:mime-type屬性來決定一個(gè)文件是否可以使用上下文的,以行為基礎(chǔ)的合并,更多信息可以看“文件內(nèi)容類型”一節(jié)。)
- 對于每一個(gè)沖突的文件,Subversion放置三個(gè)額外的未版本化文件到你的工作拷貝:
filename.mine
你更新前的文件,沒有沖突標(biāo)志,只是你最新更改的內(nèi)容。(如果Subversion認(rèn)為這個(gè)文件不可以合并,.mine文件不會創(chuàng)建,因?yàn)樗凸ぷ魑募嗤?
filename.rOLDREV
這是你的做更新操作以前的BASE版本文件,就是你在上次更新之后未作更改的版本。
filename.rNEWREV
這是你的Subversion客戶端從服務(wù)器剛剛收到的版本,這個(gè)文件對應(yīng)版本庫的HEAD版本。
這里OLDREV是你的.svn目錄中的修訂版本號,NEWREV是版本庫中HEAD的版本號。
舉一個(gè)例子,Sally修改了sandwich.txt,Harry剛剛改變了他的本地拷貝中的這個(gè)文件并且提交到服務(wù)器,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,直到你的三個(gè)臨時(shí)文件被刪掉。
$ 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
如果你遇到?jīng)_突,三件事你可以選擇:
- “手動”合并沖突文本(檢查和修改文件中的沖突標(biāo)志)。
- 用某一個(gè)臨時(shí)文件覆蓋你的工作文件。
- 運(yùn)行svn revert <filename>來放棄所有的本地修改。
一旦你解決了沖突,你需要通過命令svn resolved讓Subversion知道,這樣就會刪除三個(gè)臨時(shí)文件,Subversion就不會認(rèn)為這個(gè)文件是在沖突狀態(tài)了。[6]
$ svn resolved sandwich.txt
Resolved conflicted state of 'sandwich.txt'
第一次嘗試解決沖突讓人感覺很害怕,但經(jīng)過一點(diǎn)訓(xùn)練,它簡單的像是騎著車子下坡。
這里一個(gè)簡單的例子,由于不良的交流,你和同事Sally,同時(shí)編輯了sandwich.txt。Sally提交了修改,當(dāng)你準(zhǔn)備更新你的工作拷貝,沖突發(fā)生了,我們不得不去修改sandwich.txt來解決這個(gè)問題。首先,看一下這個(gè)文件:
$ 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
小于號、等于號和大于號串是沖突標(biāo)記,并不是沖突的數(shù)據(jù),你一定要確定這些內(nèi)容在下次提交之前得到刪除,前兩組標(biāo)志中間的內(nèi)容是你在沖突區(qū)所做的修改:
<<<<<<< .mine
Salami
Mortadella
Prosciutto
=======
后兩組之間的是Sally提交的修改沖突:
=======
Sauerkraut
Grilled Chicken
>>>>>>> .r2
通常你并不希望只是刪除沖突標(biāo)志和Sally的修改—當(dāng)她收到三明治時(shí),會非常的吃驚。所以你應(yīng)該走到她的辦公室或是拿起電話告訴Sally,你沒辦法從從意大利熟食店得到想要的泡菜。[7]一旦你們確認(rèn)了提交內(nèi)容后,修改文件并且刪除沖突標(biāo)志。
Top piece of bread
Mayonnaise
Lettuce
Tomato
Provolone
Salami
Mortadella
Prosciutto
Creole Mustard
Bottom piece of bread
現(xiàn)在運(yùn)行svn resolved,你已經(jīng)準(zhǔn)備好提交了:
$ svn resolved sandwich.txt
$ svn commit -m "Go ahead and use my sandwich, discarding Sally's edits."
現(xiàn)在我們準(zhǔn)備好提交修改了,注意svn resolved不像我們本章學(xué)過的其他命令一樣需要參數(shù),在任何你認(rèn)為解決了沖突的時(shí)候,只需要小心運(yùn)行svn resolved,—一旦刪除了臨時(shí)文件,Subversion會讓你提交這文件,即使文件中還存在沖突標(biāo)記。
記住,如果你修改沖突時(shí)感到混亂,你可以參考subversion生成的三個(gè)文件—包括你未作更新的文件。你也可以使用三方交互合并工具檢驗(yàn)這三個(gè)文件。
如果你只是希望取消你的修改,你可以僅僅拷貝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
如果你得到?jīng)_突,經(jīng)過檢查你決定取消自己的修改并且重新編輯,你可以恢復(fù)你的修改:
$ svn revert sandwich.txt
Reverted 'sandwich.txt'
$ ls sandwich.*
sandwich.txt
注意,當(dāng)你恢復(fù)一個(gè)沖突的文件時(shí),不需要再運(yùn)行svn resolved。
最后!你的修改結(jié)束了,你合并了服務(wù)器上所有的修改,你準(zhǔn)備好提交修改到版本庫。
svn commit命令發(fā)送所有的修改到版本庫,當(dāng)你提交修改時(shí),你需要提供一些描述修改的日志信息,你的信息會附到這個(gè)修訂版本上,如果信息很簡短,你可以在命令行中使用--message(或-m)選項(xiàng):
$ svn commit -m "Corrected number of cheese slices."
Sending sandwich.txt
Transmitting file data .
Committed revision 3.
然而,如果你把寫日志信息當(dāng)作工作的一部分,你也許會希望告訴Subversion通過一個(gè)文件名得到日志信息,使用--file選項(xiàng):
$ svn commit -F logmsg
Sending sandwich.txt
Transmitting file data .
Committed revision 4.
如果你沒有指定--message或者--file選項(xiàng),Subversion會自動地啟動你最喜歡的編輯器(見“配置”一節(jié)的editor-cmd部分)來編輯日志信息。
提示
如果你使用編輯器撰寫日志信息時(shí)希望取消提交,你可以直接關(guān)掉編輯器,不要保存,如果你已經(jīng)做過保存,只要簡單的刪掉所有的文本并再次保存,然后退出。
$ svn commit
Waiting for Emacs...Done
Log message unchanged or not specified
a)bort, c)ontinue, e)dit
a
$
版本庫不知道也不關(guān)心你的修改作為一個(gè)整體是否有意義,它只檢查是否有其他人修改了同一個(gè)文件,如果別人已經(jīng)這樣做了,你的整個(gè)提交會失敗,并且提示你一個(gè)或多個(gè)文件已經(jīng)過時(shí)了:
$ 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
…
(錯(cuò)誤信息的精確措辭依賴于網(wǎng)絡(luò)協(xié)議和你使用的服務(wù)器,但對于所有的情況,其思想完全一樣。)
此刻,你需要運(yùn)行svn update來處理所有的合并和沖突,然后再嘗試提交。
我們已經(jīng)覆蓋了Subversion基本的工作周期,還有許多其它特性可以管理你得版本庫和工作拷貝,但是只使用前面介紹的命令你就可以很進(jìn)行日常工作了,我們還會覆蓋更多用的還算頻繁的命令。
[4] 當(dāng)然沒有任何東西是在版本庫里被刪除了—只是在版本庫的HEAD里消失了,你可以通過檢出(或者更新你的工作拷貝)你做出刪除操作的前一個(gè)修訂版本來找回所有的東西,詳細(xì)請見“找回刪除的項(xiàng)目”一節(jié)。
[5] 而且你也沒有WAN卡,考慮到你得到我們,哈!
[6] 你也可以手工的刪除這三個(gè)臨時(shí)文件,但是當(dāng)Subversion會給你做時(shí)你會自己去做嗎?我們是這樣想的。
[7] 如果你向他們詢問,他們非常有理由把你帶到城外的鐵軌上。
檢驗(yàn)歷史
你的版本庫就像是一臺時(shí)間機(jī)器,它記錄了所有提交的修改,允許你檢查文件或目錄以及相關(guān)元數(shù)據(jù)的歷史。通過一個(gè)Subversion命令你可以根據(jù)時(shí)間或修訂號取出一個(gè)過去的版本(或者恢復(fù)現(xiàn)在的工作拷貝),然而,有時(shí)候我們只是想看看歷史而不想回到歷史。
有許多命令可以為你提供版本庫歷史:
svn log
展示給你主要信息:每個(gè)版本附加在版本上的作者與日期信息和所有路徑修改。
svn diff
顯示特定修改的行級詳細(xì)信息。
svn cat
取得在特定版本的某一個(gè)文件顯示在當(dāng)前屏幕。
svn list
顯示一個(gè)目錄在某一版本存在的文件。
找出一個(gè)文件或目錄的歷史信息,使用svn log命令,svn log將會提供你一條記錄,包括:誰對文件或目錄作了修改、哪個(gè)修訂版本作了修改、修訂版本的日期和時(shí)間、還有如果你當(dāng)時(shí)提供了日志信息,也會顯示。
$ 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
------------------------------------------------------------------------
注意日志信息缺省根據(jù)時(shí)間逆序排列,如果希望察看特定順序的一段修訂版本或者單一版本,使用--revision(-r) 選項(xiàng):
$ 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
你也可以檢查單個(gè)文件或目錄的日志歷史,舉個(gè)例子:
$ svn log foo.c
…
$ svn log http://foo.com/svn/trunk/code/foo.c
…
這樣只會顯示這個(gè)工作文件(或者URL)做過修訂的版本的日志信息。
如果你希望得到目錄和文件更多的信息,你可以對svn log命令使用--verbose (-v)開關(guān),因?yàn)镾ubversion允許移動和復(fù)制文件和目錄,所以跟蹤路徑修改非常重要,在詳細(xì)模式下,svn log 輸出中會包括一個(gè)路徑修改的歷史:
$ 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也有一個(gè)--quiet (-q)選項(xiàng),會禁止日志信息的主要部分,當(dāng)與--verbose結(jié)合使用,僅會顯示修改的文件名。
為什么svn log給我一個(gè)空的回應(yīng)?
當(dāng)使用Subversion一些時(shí)間后,許多用戶會遇到這種情況:
$ svn log -r 2
------------------------------------------------------------------------
$
乍一看,好像是一個(gè)錯(cuò)誤,但是想一下修訂版本號是作用在版本庫整體之上的,如果你沒有提供路徑,svn log會使用當(dāng)前目錄作為默認(rèn)的目標(biāo),所以,作為結(jié)果,如果你對一個(gè)本身和子目錄在指定版本到現(xiàn)在沒有做過修改的目錄運(yùn)行這個(gè)命令,你會得到空的日志。如果你希望察看某個(gè)版本做的修改的日志,只需要直接告訴svn log使用版本庫頂級的目錄作為參數(shù),例如svn log -r 2 http://svn.collab.net/repos/svn。
我們已經(jīng)看過svn diff—使用標(biāo)準(zhǔn)區(qū)別文件格式顯示區(qū)別,它在提交前用來顯示本地工作拷貝與版本庫的區(qū)別。
事實(shí)上,svn diff有三種不同的用法:
- 檢查本地修改
- 比較工作拷貝與版本庫
- 比較版本庫與版本庫
像我們看到的,不使用任何參數(shù)調(diào)用時(shí),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
$
如果傳遞一個(gè)--revision(-r)參數(shù),你的工作拷貝會與指定的版本比較。
$ 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)傳遞兩個(gè)通過冒號分開的版本號,這兩個(gè)版本會進(jìn)行比較。
$ 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
$
與前一個(gè)修訂版本比較更方便的辦法是使用--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
$
最后,即使你在本機(jī)沒有工作拷貝,還是可以比較版本庫的修訂版本,只需要在命令行中輸入合適的URL:
$ svn diff -c 5 http://svn.example.com/repos/example/trunk/text/rules.txt
…
$
通過svn cat和svn list,你可以在未修改工作修訂版本的情況下查看文件和目錄的內(nèi)容,實(shí)際上,你甚至也不需要有一個(gè)工作拷貝。
如果你只是希望檢查一個(gè)過去的版本而不希望察看它們的區(qū)別,使用svn cat:
$ svn cat -r 2 rules.txt
Be kind to others
Freedom = Chocolate Ice Cream
Everything in moderation
Chew with your mouth open
$
你可以重定向輸出到一個(gè)文件:
$ svn cat -r 2 rules.txt > rules.txt.v2
$
svn list可以在不下載文件到本地目錄的情況下來察看目錄中的文件:
$ svn list http://svn.collab.net/repos/svn
README
branches/
clients/
tags/
trunk/
如果你希望察看詳細(xì)信息,你可以使用--verbose(-v) 參數(shù):
$ 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/
這些列告訴你文件和目錄最后修改的修訂版本、做出修改的用戶、如果是文件還會有文件的大小,最后是修改日期和項(xiàng)目的名字。
警告
沒有任何參數(shù)的svn list命令缺省使用當(dāng)前工作拷貝的版本庫URL,而不是本地工作拷貝的目錄。畢竟,如果你希望列出本地目錄,你只需要使用ls(或任何合理的非UNIX等價(jià)物)。
除了以上的命令,你可以使用帶參數(shù)--revision的svn update和svn checkout來使整個(gè)工作拷貝“回到過去”[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實(shí)例來“回退”修改,但是你不能提交修改,你獲得有新修訂版本的過時(shí)工作拷貝也是沒有用的。關(guān)于如何“回退”,我們可以看“找回刪除的項(xiàng)目”一節(jié)。
最后,如果你構(gòu)建了一個(gè)版本,并且希望從Subversion打包文件,但是你不希望有討厭的.svn目錄,這時(shí)你可以導(dǎo)出版本庫的一部分文件而沒有.svn目錄。就像svn update和svn checkout,你也可以傳遞--revision選項(xiàng)給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是一個(gè)時(shí)間機(jī)器。