### Subversion實戰
是時候從抽象轉到具體了,在本小節,我們會展示一個Subversion真實使用的例子。
### 工作拷貝
你已經閱讀過了關于工作拷貝的內容,現在我們要講一講客戶端怎樣建立和使用它。
一個Subversion工作拷貝是你本地機器一個普通的目錄,保存著一些文件,你可以任意的編輯文件,而且如果是源代碼文件,你可以像平常一樣編譯,你的工作拷貝是你的私有工作區,在你明確的做了特定操作之前,Subversion不會把你的修改與其他人的合并,也不會把你的修改展示給別人。
當你在工作拷貝作了一些修改并且確認它們工作正常之后,Subversion提供了一個命令可以“發布”你的修改給項目中的其他人(通過寫到版本庫),如果別人發布了各自的修改,Subversion提供了手段可以把這些修改與你的工作目錄進行合并(通過讀取版本庫)。
一個工作拷貝也包括一些由Subversion創建并維護的額外文件,用來協助執行這些命令。通常情況下,你的工作拷貝每一個文件夾有一個以`.svn`為名的文件夾,也被叫做工作拷貝*管理目錄*,這個目錄里的文件能夠幫助Subversion識別哪一個文件做過修改,哪一個文件相對于別人的工作已經過期了。
一個典型的Subversion的版本庫經常包含許多項目的文件(或者說源代碼),通常每一個項目都是版本庫的子目錄,在這種安排下,一個用戶的工作拷貝往往對應版本庫的的一個子目錄。
舉一個例子,你的版本庫包含兩個軟件項目,`paint`和`calc`。每個項目在它們各自的頂級子目錄下,見[圖2.6 “版本庫的文件系統”]( "圖2.6.版本庫的文件系統")。
**圖2.6.版本庫的文件系統**

為了得到一個工作拷貝,你必須*檢出*(*check out*)版本庫的一個子樹,(術語“check out”聽起來像是鎖定或者保存資源,實際上不是,只是簡單的得到一個項目的私有拷貝),舉個例子,你檢出 `/calc`,你可以得到這樣的工作拷貝:
~~~
$ svn checkout http://svn.example.com/repos/calc
A calc
A calc/Makefile
A calc/integer.c
A calc/button.c
$ ls -A calc
Makefile integer.c button.c .svn/
~~~
列表中的A表示Subversion增加了一些條目到工作拷貝,你現在有了一個`/calc`的個人拷貝,有一個附加的目錄―`.svn`―保存著前面提及的Subversion需要的額外信息。
**版本庫的URL**
Subversion可以通過多種方式訪問―本地磁盤訪問,或各種各樣不同的網絡協議,但一個版本庫地址永遠都是一個URL,表格2.1描述了不同的URL模式對應的訪問方法。
**表2.1.版本庫訪問URL**
| 模式 | 訪問方法 |
|-----|-----|
| `file:///` | 直接版本庫訪問(本地磁盤)。 |
| `http://` | 通過配置Subversion的Apache服務器的WebDAV協議。 |
| `https://` | 與`http://`相似,但是包括SSL加密。 |
| `svn://` | 通過`svnserve`服務自定義的協議。 |
| `svn+ssh://` | 與`svn://`相似,但通過SSH封裝。 |
關于Subversion解析URL的更多信息,見[“Subversion版本庫URL”一節]( "Subversion版本庫URL")。
假定你修改了`button.c`,因為`.svn`目錄記錄著文件的修改日期和原始內容,Subversion可以告訴你已經修改了文件,然而,在你明確告訴它之前,Subversion不會將你的改變公開。將改變公開的操作被叫做提交(*committing*,或者是*checking in*)修改到版本庫。
發布你的修改給別人,你可以使用Subversion的提交(**commit**)命令:
~~~
$ svn commit button.c
Sending button.c
Transmitting file data .
Committed revision 57.
~~~
這時你對`button.c`的修改已經提交到了版本庫,如果其他人取出了`/calc`的一個工作拷貝,他們會看到這個文件最新的版本。
假設你有個合作者,Sally,她和你同時取出了`/calc`的一個工作拷貝,你提交了你對`button.c`的修改,Sally的工作拷貝并沒有改變,Subversion只在用戶要求的時候才改變工作拷貝。
要使項目最新,Sally可以要求Subversion*更新*她的工作備份,通過使用更新(**update**)命令,將結合你和所有其他人在她上次更新之后的改變到她的工作拷貝。
~~~
$ pwd
/home/sally/calc
$ ls -A
.svn/ Makefile integer.c button.c
$ svn update
U button.c
~~~
**svn update**命令的輸出表明Subversion更新了`button.c`的內容,注意,Sally不必指定要更新的文件,subversion利用`.svn`以及版本庫的進一步信息決定哪些文件需要更新。
### 修訂版本
一個**svn commit**操作可以作為一個原子事務操作發布任意數量文件和目錄的修改,在你的工作拷貝里,你可以改變文件內容、刪除、改名和拷貝文件和目錄,然后作為一個整體提交。
在版本庫中,每一次提交被當作一次原子事務操作:要么所有的改變發生,要么都不發生,Subversion努力保持原子性以應對程序錯誤、系統錯誤、網絡問題和其他用戶行為。
每當版本庫接受了一個提交,文件系統進入了一個新的狀態,叫做一次修訂(*revision*),每一個修訂版本被賦予一個獨一無二的自然數,一個比一個大,初始修訂號是0,只創建了一個空目錄,沒有任何內容。
[圖2.7 “版本庫”]( "圖2.7.版本庫")可以更形象的描述版本庫,想象有一組修訂號,從0開始,從左到右,每一個修訂號有一個目錄樹掛在它下面,每一個樹好像是一次提交后的版本庫“快照”。
**圖2.7.版本庫**

**全局修訂號**
不像其他版本控制系統,Subversion的修訂號是針對整個*目錄樹*的,而不是單個文件。每一個修訂號代表了一次提交后版本庫整個目錄樹的特定狀態,另一種理解是修訂號N代表版本庫已經經過了N次提交。當Subversion用戶討論“`foo.c`的修訂號5”時,他們的實際意思是“在修訂號5時的`foo.c`”。需要注意的是,修訂號N和M并*不*表示一個文件需要不同。因為CVS使用每一個文件一個修訂號的策略,CVS用戶可能希望察看[附錄A, *Subversion對于CVS用戶*]( "附錄A.Subversion對于CVS用戶")來得到更多細節。
需要特別注意的是,工作拷貝并不一定對應版本庫中的單個修訂版本,他們可能包含多個修訂版本的文件。舉個例子,你從版本庫檢出一個工作拷貝,最近的修訂號是4:
~~~
calc/Makefile:4
integer.c:4
button.c:4
~~~
此刻,工作目錄與版本庫的修訂版本4完全對應,然而,你修改了`button.c`并且提交之后,假設沒有別的提交出現,你的提交會在版本庫建立修訂版本5,你的工作拷貝會是這個樣子的:
~~~
calc/Makefile:4
integer.c:4
button.c:5
~~~
假設此刻,Sally提交了對`integer.c`的修改,建立修訂版本6,如果你使用**svn update**來更新你的工作拷貝,你會看到:
~~~
calc/Makefile:6
integer.c:6
button.c:6
~~~
Sally對`integer.c`的改變會出現在你的工作拷貝,你對`button.c`的改變還在,在這個例子里,`Makefile`在4、5、6修訂版本都是一樣的,但是Subversion會把他的`Makefile`的修訂號設為6來表明它是最新的,所以你在工作拷貝頂級目錄作一次干凈的更新,會使得所有內容對應版本庫的同一修訂版本。
### 工作拷貝怎樣追蹤版本庫
對于工作拷貝的每一個文件,Subversion在管理區域`.svn/`記錄兩項關鍵的信息:
-
工作文件所作為基準的修訂版本(叫做文件的*工作修訂版本*)和
-
一個本地拷貝最后更新的時間戳。
給定這些信息,通過與版本庫通訊,Subversion可以告訴我們工作文件是處與如下四種狀態的那一種:
未修改且是當前的
文件在工作目錄里沒有修改,在工作修訂版本之后沒有修改提交到版本庫。**svn commit**操作不做任何事情,**svn update**不做任何事情。
本地已修改且是當前的
在工作目錄已經修改,從基本修訂版本之后沒有修改提交到版本庫。本地修改沒有提交,因此**svn commit**會成功的提交,**svn update**不做任何事情。
未修改且不是當前的了
這個文件在工作目錄沒有修改,但在版本庫中已經修改了。這個文件最終將更新到最新版本,成為當時的公共修訂版本。**svn commit**不做任何事情,**svn update**將會取得最新的版本到工作拷貝。
本地已修改且不是最新的
這個文件在工作目錄和版本庫都得到修改。一個**svn commit**將會失敗,這個文件必須首先更新,**svn update**命令會合并公共和本地修改,如果Subversion不可以自動完成,將會讓用戶解決沖突。
這看起來需要記錄很多事情,但是**svn status**命令可以告訴你工作拷貝中文件的狀態,關于此命令更多的信息,請看[“**svn status**”一節]( "svn status")。
### 修訂版本混合的限制
作為通常的原則,Subversion期望盡可能的靈活,一個靈活性的表現就是能夠在工作拷貝中混合有不同的修訂版本。
起初,為什么把這種靈活性看作一種特性并沒有完全看清楚,這也不是一個任務。完成了提交之后,干凈的提交的文件比其他文件有更加新的版本,這看起來有些混亂,但是像以前說過的,通過**svn update**可以使整個版本統一起來, 怎么會有人*故意的*混合版本呢?
假設你的項目非常復雜,有時候需要強制地使工作拷貝的一部分“回到”某一個日期,你可以在第3章學習如何操作。或許你也希望測試某一目錄下子模塊早期的版本,或許你想檢查某一文件過去的一系列版本在最新目錄樹環境下的表現。
無論你在工作拷貝中如何利用混合版本,對于這種靈活性是有限制的。
首先,你不可以提交一個不是完全最新的文件或目錄,如果有個新的版本存在于版本庫,你的刪除操作會被拒絕,這防止你不小心破壞你沒有見到的東西。
第二,如果目錄已經不是最新的了,你不能提交一個目錄的元數據更改。你將會在第6章學習附加“屬性”,一個目錄的工作修訂版本定義了許多條目和屬性,因而對一個過期的版本提交屬性會破壞一些你沒有見到的屬性。
- 第1章介紹
- Subversion的歷史
- Subversion的特性
- Subversion的架構
- 安裝Subversion
- Subversion的組件
- 快速入門
- 第2章基本概念
- 版本模型
- Subversion實戰
- 摘要
- 第3章指導教程
- 導入
- 修訂版本: 號碼、關鍵字和日期,噢,我的!
- 初始化的Checkout
- 基本的工作周期
- 檢驗歷史
- 其他有用的命令
- 摘要
- 第4章分支與合并
- 使用分支
- 在分支間拷貝修改
- 常見用例
- 轉換工作拷貝
- 標簽
- 分支維護
- 摘要
- 第5章版本庫管理
- 版本庫的創建和配置
- 版本庫維護
- 添加項目
- 摘要
- 第6章配置服務器
- 網絡模型
- svnserve,一個自定義的服務器
- httpd,Apache的HTTP服務器
- 支持多種版本庫訪問方法
- 第7章高級主題
- 屬性
- Peg和實施修訂版本
- 外部定義
- 賣主分支
- 本地化
- Subversion版本庫URL
- 第8章開發者信息
- 使用API
- 進入工作拷貝的管理區
- WebDAV
- 使用內存池編程
- 為Subversion做貢獻
- 第9章Subversion完全參考
- svn add
- svn blame
- svn cat
- svn checkout
- svn cleanup
- svn commit
- svn copy
- svn delete
- svn diff
- svn export
- svn help
- svn import
- svn info
- svn list
- svn log
- svn merge
- svn mkdir
- svn move
- svn propdel
- svn propedit
- svn propget
- svn proplist
- svn propset
- svn resolved
- svn revert
- svn status
- svn switch
- svn update
- svnadmin
- svnadmin create
- svnadmin deltify
- svnadmin dump
- svnadmin help
- svnadmin hotcopy
- svnadmin list-dblogs
- svnadmin list-unused-dblogs
- svnadmin load
- svnadmin lstxns
- svnadmin recover
- svnadmin rmtxns
- svnadmin setlog
- svnadmin verify
- svnlook
- svnlook author
- svnlook cat
- svnlook changed
- svnlook date
- svnlook diff
- svnlook dirs-changed
- svnlook help
- svnlook history
- svnlook info
- svnlook log
- svnlook propget
- svnlook proplist
- svnlook tree
- svnlook uuid
- svnlook youngest
- svnserve
- svnversion
- mod_dav_svn Configuration Directives
- 附錄A.Subversion對于CVS用戶
- 目錄的版本
- 更多離線操作
- 區分狀態和更新
- 分支和標簽
- 元數據屬性
- 沖突解決
- 二進制文件和轉化
- 版本化的模塊
- 認證
- 轉化CVS版本庫到Subversion
- 附錄C.WebDAV和自動版本化
- 自動版本化交互性
- Subversion和DeltaV
- 術語表