手冊

Subversion 實戰

工作副本

您已經閱讀過關於工作副本的內容;現在我們將示範 Subversion 客戶端如何建立和使用它們。

Subversion 工作副本是您本機系統上的一般目錄樹,其中包含檔案的集合。您可以隨意編輯這些檔案,如果它們是原始碼檔案,您可以像平常一樣從它們編譯您的程式。您的工作副本是您自己的私人工作區:除非您明確告知 Subversion 執行此操作,否則 Subversion 永遠不會合併其他人的變更,也不會讓其他人可以使用您自己的變更。

在您對工作副本中的檔案進行了一些變更並驗證它們可以正常運作後,Subversion 為您提供命令,以發布您的變更給與您一起參與專案的其他人員(透過寫入儲存庫)。如果其他人發布他們自己的變更,Subversion 為您提供命令,將這些變更合併到您的工作目錄中(透過從儲存庫讀取)。

工作副本也包含一些額外的檔案,這些檔案由 Subversion 建立和維護,以協助它執行這些命令。特別是,您的工作副本包含一個名為 .svn 的子目錄,也稱為工作副本管理目錄。此管理目錄中的檔案協助 Subversion 辨識哪些檔案包含未發布的變更,以及哪些檔案相對於其他人的工作而言已過時。在 1.7 版之前,Subversion 在您工作副本的每個版本控制目錄中都維護 .svn 管理子目錄。Subversion 1.7 採用完全不同的方法,現在每個工作副本只有一個管理子目錄,它是該工作副本根目錄的直接子目錄。

典型的 Subversion 儲存庫通常保存數個專案的檔案(或原始碼);通常,每個專案都是儲存庫檔案系統樹中的一個子目錄。在這種安排中,使用者的工作副本通常會對應到儲存庫的特定子樹。

例如,假設您有一個包含兩個軟體專案的儲存庫。

圖 2.6. 儲存庫的檔案系統

The Repository's Filesystem

換句話說,儲存庫的根目錄有兩個子目錄:paintcalc

要取得工作副本,您必須檢出儲存庫的某些子樹。(術語檢出聽起來可能與鎖定或保留資源有關,但事實並非如此;它只是為您建立專案的私人副本。)

假設您對 button.c 進行變更。由於 .svn 目錄會記住檔案的修改日期和原始內容,因此 Subversion 可以判斷您已變更了檔案。但是,在您明確告知 Subversion 之前,Subversion 不會公開您的變更。發布您的變更的行為更常被稱為將變更提交(或簽入)到儲存庫。

要將您的變更發布給其他人,您可以使用 Subversion 的 commit 命令。

現在您對 button.c 的變更已提交到儲存庫;如果另一個使用者檢出 /calc 的工作副本,他們將在檔案的最新版本中看到您的變更。

假設您有一位協作者 Sally,她與您同時檢出了 /calc 的工作副本。當您將對 button.c 的變更提交時,Sally 的工作副本保持不變;Subversion 僅在使用者請求時修改工作副本。

為了使她的專案保持最新,Sally 可以要求 Subversion 更新她的工作副本,方法是使用 Subversion update 命令。這會將您的變更以及自她檢出以來已提交的任何其他變更併入她的工作副本中。

請注意,Sally 不需要指定要更新哪些檔案;Subversion 使用 .svn 目錄中的資訊,以及儲存庫中的更多資訊,來決定哪些檔案需要更新。

儲存庫 URL

可以透過許多不同的方法存取 Subversion 儲存庫 - 在本機磁碟上,或透過各種網路協定。但是,儲存庫位置始終是一個 URL。URL 結構描述指示存取方法

表 2.1. 儲存庫存取 URL

結構描述存取方法
file:// 直接在本機或網路磁碟機上存取儲存庫。
http:// 透過 WebDAV 協定存取支援 Subversion 的 Apache 伺服器。
https:// http:// 相同,但具有 SSL 加密。
svn:// 透過自訂協定,未經身分驗證的 TCP/IP 存取 svnserve 伺服器。
svn+ssh:// 透過自訂協定,經過身分驗證、加密的 TCP/IP 存取 svnserve 伺服器。

在大多數情況下,Subversion 的 URL 使用標準語法,允許將伺服器名稱和埠號指定為 URL 的一部分。file:// 存取方法通常用於本機存取,儘管它可以用於網路主機的 UNC 路徑。因此,URL 的形式為 file://hostname/path/to/repos。對於本機電腦,URL 的 hostname 部分必須不存在或為 localhost。因此,本機路徑通常會顯示三個斜線,file:///path/to/repos

此外,Windows 平台上的 file:// 結構描述使用者將需要使用非官方的標準語法來存取位於同一部電腦上,但在與用戶端目前工作磁碟機不同的磁碟機上的儲存庫。以下兩種 URL 路徑語法中的任何一種都適用,其中 X 是儲存庫所在的磁碟機

file:///X:/path/to/repos
...
file:///X|/path/to/repos
...
      

請注意,即使 Windows 上路徑的原生(非 URL)形式使用反斜線,URL 也使用普通斜線。

您可以透過網路共用存取 FSFS 儲存庫,但由於以下各種原因,建議這樣做

  • 您正在授予所有使用者直接寫入權限,因此他們可能會意外刪除或損壞儲存庫檔案系統。

  • 並非所有網路檔案共用協定都支援 Subversion 所需的鎖定。有一天,您會發現您的儲存庫已被微妙地損壞

  • 您必須以正確的方式設定存取權限。在這方面,SAMBA 特別困難。

  • 如果一個人安裝了較新版本的用戶端,該用戶端升級了儲存庫格式,那麼在其他所有人也升級到新的用戶端版本之前,他們將無法存取儲存庫。

版本

svn commit 操作可以將對任意數量的檔案和目錄的變更發布為單個原子交易。在您的工作副本中,您可以變更檔案的內容、建立、刪除、重新命名和複製檔案和目錄,然後將完整的變更集合作為一個單元提交。

在儲存庫中,每次提交都被視為一個原子交易:所有提交的變更都會發生,或者都不會發生。Subversion 在面對程式崩潰、系統崩潰、網路問題和其他使用者的操作時,仍保持這種原子性。

每次儲存庫接受提交時,都會建立檔案系統樹的新狀態,稱為版本。每個版本都會被指派一個唯一的自然數,該數字比前一個版本的編號大一。新建立的儲存庫的初始版本編號為零,並且僅包含一個空的根目錄。

將儲存庫視覺化為一系列樹狀結構是一個不錯的方法。想像一個版本號碼陣列,從 0 開始,從左到右延伸。每個版本號碼下方都懸掛著一個檔案系統樹,每個樹都是儲存庫在每次提交後外觀的快照

圖 2.7. 儲存庫

The Repository

重要的是要注意,工作副本不一定總是對應於儲存庫中的任何單個版本;它們可能包含來自數個不同版本的檔案。例如,假設您從最新版本為 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 可以判斷工作檔案處於以下四種狀態中的哪一種

未變更且為最新

檔案在工作目錄中未變更,並且自其工作版本以來,沒有對該檔案的變更提交到儲存庫。對檔案執行 commit 不會執行任何操作,而對檔案執行 update 也不會執行任何操作。

本機已變更且為最新

檔案已在工作目錄中變更,並且自其基本版本以來,沒有對該檔案的變更提交到儲存庫。存在尚未提交到儲存庫的本機變更,因此對檔案執行 commit 將成功發布您的變更,而對檔案執行 update 則不會執行任何操作。

未變更且已過時

檔案在工作目錄中未變更,但它已在儲存庫中變更。檔案最終應更新,以使其與公開版本保持最新。對檔案執行 commit 不會執行任何操作,而對檔案執行 update 將把最新的變更摺疊到您的工作副本中。

本機已變更且已過時

檔案已在工作目錄和儲存庫中變更。對檔案執行 commit 將失敗並顯示過時錯誤。應先更新檔案;update 命令將嘗試將公開變更與本機變更合併。如果 Subversion 無法以合理的方式自動完成合併,則會將衝突留給使用者解決。

TortoiseSVN 首頁