1. 程式人生 > >SVN 學習筆記二(一口氣學會SVN)

SVN 學習筆記二(一口氣學會SVN)

我打算一口氣講完SVN的使用,所以,在看之前呢,請先深深的吸一口氣(怎麼聽著像黑龍公主),當然吸完後還是要撥出來的。不要憋著了。

我們可能希望一來就直接操作。列出一堆命令。詳細的命令引數等資訊,我們都可以加入 --help 選項獲取,下面不會詳細介紹。除非必要。現在先看下面的例子:

$svn --help 

usage: svn <subcommand> [options] [args]

Subversion command-line client, version 1.6.12.

Type 'svn help <subcommand>' for help on a specific subcommand.

Type 'svn --version' to see the program version and RA modules

  or 'svn --version --quiet' to see just the version number.

Most subcommands take file and/or directory arguments, recursing

on the directories.  If no arguments are supplied to such a

command, it recurses on the current directory (inclusive) by default.

Available subcommands:

   add

   blame (praise, annotate, ann)

   cat

   changelist (cl)

   checkout (co)

   cleanup

   commit (ci)

   copy (cp)

   delete (del, remove, rm)

   diff (di)

   export

   help (?, h)

   import

   info

   list (ls)

   lock

   log

   merge

   mergeinfo

   mkdir

   move (mv, rename, ren)

   propdel (pdel, pd)

   propedit (pedit, pe)

   propget (pget, pg)

   proplist (plist, pl)

   propset (pset, ps)

   resolve

   resolved

   revert

   status (stat, st)

   switch (sw)

   unlock

   update (up)

Subversion is a tool for version control.

好了,什麼都出來了。一大堆資訊。慢慢讀吧。可是這樣的方式,對我們使用SVN並無指導意義。什麼時候用什麼命令? 下面就來說一下SVN的基本使用,在此之前,還有兩個重要的東西需要理解。

SVN 除了可以讓你追溯歷史,還有一個重要的功能,便是多人協作。我們要解決的問題不僅僅是可以從歷史中恢復。還有如果多人同時修改一個檔案,那麼該以誰的為主呢?

所以在SVN中,我們有兩種使用模式:

Lock-Modify-Unlock

簡單的說就是,給需要修改的檔案加鎖,然後修改,然後解鎖。

這是一個很好的辦法。但是如果一個檔案被鎖住了,那麼其他人就不能修改了。而此時如果是我在修改檔案頭,而你需要修改檔案末尾的話,你也只能等我修改完。這樣是很浪費你的時間的。所以我們又有另外一種模式。

Copy-Modify-Merge

這是一種很高階的模式,從庫中拷貝一份,修改,然後根據拷貝的和庫中的不同,在合併。為什麼說高階呢,因為合併是一個很複雜的過程。很可能失敗。但是這種方法卻儘可能使大家不受影響。例如你和我同時修改一個檔案,我改檔案頭,你改檔案尾,然後一提交,就給合成一份了。不會互相打擾。事實上問題比這複雜的多。

好了,說了這麼多廢話。我們可以正式開始了。

雖然一般情況,我們是不用自己去建立一個SVN庫的,現在為了說明流暢,我們從建立一個庫開始。

$svnadmin create  /var/idp/repos

於是我們建立了一個SVN庫。到下面看看

$ls /var/idp/repos

conf  db  format  hooks  locks  README.txt

我們的庫就建立好了。這裡不多說, svnadmin是一個高階命令,我們基本用不到。

匯入需要管理的檔案:

$svn import /home/madic/code file:///var/idp/repos -m "init code"

Adding         /home/madic/code/signo

Adding         /home/madic/code/signo/sigset.c

Adding  (bin)  /home/madic/code/signo/wait

Adding         /home/madic/code/signo/wait.c

Committed revision 1.

這裡版本變為1,初始版本為0。  每次對庫的操作改變,都會產生一個新的版本。版本是我們追溯歷史的一個索引。在版本管理中非常重要。當前庫中最新的版本可以用HEAD表示。HEAD版也就是庫中最新版本。

我們把 /home/madic/code 檔案下的檔案目錄都匯入了svn庫,從此,他們就被時光機管理,資料永不丟失(當然你幹掉時光機,資料還是會丟失的)。

注意 (bin) 表示這是一個二進位制檔案,非文字檔案。

除了import 外,我們還可以用 svn add 新增檔案。

使用list命令檢視庫中檔案

$svn  list  file:///var/idp/repos

signo/

signo/sigset.c

signo/wait

signo/wait.c

現在,我們開始工作了。那麼,就使用 CMC(Copy-Modify-Merge)模式吧。

如何建立一個Working Copy 呢?看:

$svn checkout file:///var/idp/repos  /home/madic/code_svn

A    /home/madic/code_svn/signo

A    /home/madic/code_svn/signo/sigset.c

A    /home/madic/code_svn/signo/wait

A    /home/madic/code_svn/signo/wait.c

Checked out revision 1.

恭喜我們現在擁有一個Working Copy了,你就在這個WorkingCopy中折騰吧,只要不提交,那麼對庫來說就沒有任何影響。就算你用了 rm 不小心刪除了某個檔案,不用著急。使用update便可以找回。

$svn update 

svn update

Restored 'main.c'

At revision 1.

這裡,我們刪掉 main.c 然後到WC 下,執行 svn update 命令,就找回main.c了。

Working Copy 目錄中,Subversion如何知道檔案的情況呢,其實這些都是 .svn的功勞。每個SVN管理的WC中,都會有一個隱藏的資料夾,.svn 

$ls -la .svn

drwxr-xr-x  6 madic madic 4096 2011-07-26 11:00 .svn

如果不小心誤刪除,也可以用svn update恢復。

接下來,我們開始正常的編輯檔案。編輯之前,已定要使用svn update 來確保你編輯的檔案是最新的。如果不是最新的,那麼這個檔案就是 Out-of-date了,此時你的編輯就不能被提交到庫中。編輯時,你不必使用svn的命令了。你可以用任何編輯器編輯檔案。當你編輯完成後儲存。

$svn status -q

M       readme.txt

這個M表示此檔案被修改了。於是我們需要把她提交到庫,這樣別人才能看到我修改的東西。

$svn commit -m "我修改了檔案內容" readme.txt

svn commit -m "modify" readme.txt

Sending        readme.txt

Transmitting file data .

Committed revision 8.

檔案被提交,版本更新到8.

這樣,我們就完成了一個最基本的SVN操作流程。也許如果沒有什麼大事,我們就到此結束了。難道還有什麼問題嗎?

上面提到,我們在修改的同時,可能別人也在修改。所以要儘量在每次修改的時候,保持我們的WC和庫中的是同步的,也就是最新的。我們使用svn update來使自己的working copy是最新的。我們也可以用一個新的命令來看WC的狀態。

$svn status -u -v readme.txt

M                8        8  madic        readme.txt

M     *          8        3  madic        foo.c

我們看到readme.txt 目前是M(modify)狀態,說明此檔案被改了。當前版本和最新版本都是,使用者是madic

foo.c 多了個星號,這表明foo.c 已經out-of-date 了。也就是說,我們在修改的版本,已經不是最新的了。在我們修改的時候,已經有人提交了新的版本。

除了 M表示修改,還有 U表示更新,D表示刪除,表示新增, C表示衝突。

有時候有兩個MM,此時並非表示美眉,而是檔案的內容和屬性都被改變了。

同樣UU表示屬性和內容都更新了。

所以,在我們提交以後,並非就結束了,此時,我們需要檢視一下狀態。如果有檔案處於C狀態,那麼說明我們遇到麻煩了。因為C表示衝突了,一定是某個人和我們在改同一個地方。

這時,最好的辦法是直接找到和我們衝突的修改人。然後溝通吧。是你死還是我亡。衝突實際上是在svn update的時候發生的。由於我編輯的太久了,你已經提交了一個新版本,我提交的時候,提示 out-of-date了,於是我svn update,衝突出現:

$ svn update

Conflict discovered in 'readme.txt'.

Select: (p) postpone, (df) diff-full, (e) edit,

        (mc) mine-conflict, (tc) theirs-conflict,

        (s) show all options:

這時幾個選擇出現了,postpone 的意思是暫時推後處理,我可能要和那個和我衝突的傢伙商量一番。 diff-full,則是比比看,到底什麼地方衝突了。edit,修改衝突合併的檔案。 mc,這個霸道,直接用我的。 tc , 底氣不足,還是用別人修改的吧。我們一切三思而後行,所以選擇了p,然後在看看檔案目錄下有什麼。

多了三個檔案:

readme.txt.mine  readme.txt.r9readme.txt  readme.txt.r8

我們來說說這三個檔案:readme.txt.mine 後最 mine是本地最新的。

readme.txt.r9 很明顯,是版本9的,這個版本正式庫中最新的版本。

readme.txt.r8  這個版本是庫中最新的版本的前一版本。

我們來看一下,現在的readme.txt

$cat readme.txt

<<<<<<< .mine

hi

=======

hello

>>>>>>> .r9

很明顯,我的版本中是hi ,而r9 的是hello

好吧,我明白了。現在假設我們很明白,或者已經和發生衝突的檔案的編輯同事商量好了。我們就要解決衝突了。

首先,上面說的三個檔案,如果存在,我們就提交不了。

其次,需要選擇一個解決方法。

$svn resolve --accepting working reademe.txt

svn resolve 是解決衝突的命令。解決的方法由--accepting 選項決定。

base  恢復到衝突前的一個版本。

mine-full  恢復到以我的修改為主的版本

their-full  恢復到庫中最新版本

working  手動解決

所以,上面的那句命令其實還有問題,因為我們還沒有手工修改檔案。

於是我們開啟readme.txt,去掉哪些衝突標識

<<<<<<< .mine

hi

=======

hello

>>>>>>> .r9

修改為 

No hi no hello

然後儲存readme.txt

在使用 

$svn resolve --accepting working reademe.txt

注意,這一步以後,並沒有真正完成衝突解決。

$svn commit -m "conflict resole"

Sending        readme.txt

Transmitting file data .

Committed revision 10.

這次提交OK。衝突至此解決。

有時候,我們編寫到一半發現有人提交了更新或者是越寫越亂,我們想放棄這次編輯,恢復到上一個版本,當然,我們可以直接rm掉,然後update,我們也可以這樣:

$svn revert readme.txt

Reverted 'readme.txt'

問題解決以後,請使用svn status 檢視一下狀態,是否正常了。

$svn status -vu readme.txt

                10       10 yinshaoxin   readme.txt

Status against revision:     10

沒有什麼MCD, ? 這些,說明狀態正常。

對於我們操作的這些,我們可以通過歷史svn log來檢視狀態。

$svn log  

r9 | yinshaoxin | 2011-07-26 13:39:12 +0800 (Tue, 26 Jul 2011) | 1 line

shaoxin

------------------------------------------------------------------------

r8 | madic | 2011-07-26 11:12:47 +0800 (Tue, 26 Jul 2011) | 1 line

modify

------------------------------------------------------------------------

r7 | madic | 2011-07-26 09:35:51 +0800 (Tue, 26 Jul 2011) | 1 line

code

------------------------------------------------------------------------

r6 | madic | 2011-07-20 15:43:52 +0800 (Wed, 20 Jul 2011) | 1 line

pa

------------------------------------------------------------------------

r5 | madic | 2011-07-20 15:42:19 +0800 (Wed, 20 Jul 2011) | 1 line

p

------------------------------------------------------------------------

r4 | madic | 2011-07-20 10:40:03 +0800 (Wed, 20 Jul 2011) | 1 line

dir

------------------------------------------------------------------------

r3 | madic | 2011-07-19 14:01:49 +0800 (Tue, 19 Jul 2011) | 1 line

keywords

------------------------------------------------------------------------

r2 | madic | 2011-07-19 13:58:24 +0800 (Tue, 19 Jul 2011) | 1 line

new test

------------------------------------------------------------------------

r1 | madic | 2011-07-15 16:56:05 +0800 (Fri, 15 Jul 2011) | 1 line

ci chage

------------------------------------------------------------------------

天哪,所有的svn日誌都顯示出來了。我們可以使用r來確定一個範圍。

這就是時光機的歷史查看了。來吧,想看哪一個版本的。

$svn log -r 5:9

------------------------------------------------------------------------

r5 | madic | 2011-07-20 15:42:19 +0800 (Wed, 20 Jul 2011) | 1 line

p

------------------------------------------------------------------------

r6 | madic | 2011-07-20 15:43:52 +0800 (Wed, 20 Jul 2011) | 1 line

pa

------------------------------------------------------------------------

r7 | madic | 2011-07-26 09:35:51 +0800 (Tue, 26 Jul 2011) | 1 line

code

------------------------------------------------------------------------

r8 | madic | 2011-07-26 11:12:47 +0800 (Tue, 26 Jul 2011) | 1 line

modify

------------------------------------------------------------------------

r9 | yinshaoxin | 2011-07-26 13:39:12 +0800 (Tue, 26 Jul 2011) | 1 line

shaoxin

------------------------------------------------------------------------

注意  -r 5:9  和 -r 9:5 是不同的順序顯示。

當然也可以指定一個檔案的版本日誌。

使用log注意,當你提交一個版本後,log並看不到這個日誌。

因為 commit 和 update是獨立的。commit並不更新本地版本。我們只有使用 update以後,在使用log則可以看到。

還有,如果你使用svn log 不指定路徑的話,那麼預設的是當前的目錄。這樣,對於其他目錄的log,我們只有一條空日誌。

$-------------------------------------------

最後不要像我一樣,日誌都是亂七八糟,請重視日誌,因為在以後查詢問題梳理版本變化的時候,會對你有很大幫助。

好了,從現在開始,你已經基本掌握SVN的用法了。如果具體命令引數不會用,請使用 help 

如果你想了解的更多一點,那麼我們繼續看下一章。