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