Subversion 最佳實務

最近因為要改進部門內使用版本控制系統時,所採用的分支、合併策略,因此在網路上找了一些資料。突然看到 Subversion Best Practices - http://svn.collab.net/repos/svn/trunk/doc/user/svn-best-p...,覺得還不錯,便著手將之譯成中文。由於在譯者在翻譯時只著重意譯,並未注重修辭,若有言不達意的地方,歡迎來函指正。

Subversion 最佳實務

這裡提供一組快速的指導原則,讓你能在每天的軟體開發工作中發揮 Subversion 的最大效用。

採用建全的儲存庫配置

儲存庫的目錄配置有許多方式。由於 branches 和 tags 只是一般的目錄,你必須在配置儲存庫的結構時,把它們考慮進去。

Subversion 官方文件建議採用專案根目錄的觀念,來代表專案在儲存庫中的掛載點。專案根目錄裡面僅包含三個子目錄:/trunk, /branches, 及 /tags。一個儲存庫裡面可包含一個或多個專案根目錄。

參考書籍: Choosing a Repository Layout.

以邏輯變更集(changesets)作為提交單位

當你將修改提交到儲存庫時,要確認你的更動反應的是單一的目的:修正一個特定的臭蟲、增加一個新的特性、或是一些特定的工作。你的提交將會產生一個 版本號碼,這號碼在往後可用來作為該次變更的 "名稱"。你可以在臭蟲資料庫中記錄這個號碼,或把它拿來作為 svn merge (合併) 的參數。

參考書藉:"Subversion and Changesets" sidebar, within chapter 4.

善用事例追蹤軟體 (issue-tracker)

盡可能試著建立 Subversion 與 issue-tracker 資料庫之間的雙向連結:

  • 盡可能在每個提交的登錄訊息 (log message) 中參引到明確的事例編號
  • 在事例中附加訊息時 (描述進度,或是關閉事例),註記相應於此事例變更作業的版本號碼

手動追蹤合併

當提交合併的結果時,切記寫下解釋合併了些什麼的描述性資訊,像是:

將 /branches/foobranch 版號 3490:4120 合併至 /trunk。

參考書藉:Tracking merges manually, and Merging a whole branch to another.

了解混合版本的工作複本

存放工作複本的目錄及檔案可以處於不同的工作版號中:這種特意的設計讓你可以混編不同的新舊版號。但是有些事實是你必須注意的:

  1. 每次的提交,都會讓你的工作複本包含不同的版號。你剛提交的變更是位於 HEAD 版號中,而其他的部份則屬於之前的版號。
  2. 有許多的情況不允許提交:
    • 若是某檔案或目錄沒有包含在 HEAD 的工作版號中,那你便不能提交其刪除動作。
    • 若是某目錄沒有包含在 HEAD 的工作版號中,那你便不能提交其變更屬性的動作。
  3. svn 更新 (update) 指令可以幫你取回整個工作版號的複本,而這也是第 2 個問題常用的解決方案。

參考書籍:The limitation of mixed revisions.

處理較大的檔案時要有耐心

Subversion 的優點之一是:在設計上,它並沒有對處理檔案的大小做限制。檔案以 "流(streamily)" 的形式在 Subversion client 及 server 兩端收送,而網路兩端只使用了少許的、定量的記憶體。

當然,有許多實務上的問題需要考量。雖然沒有必要擔心幾 K 位元組大小左右的檔案 (像是一般的原始檔),提交較大的檔案會花費大量的時間及空間 (像是幾十或幾百 mega 位元組大小的檔案)。

首先,記得 Subversion 的工作複本會在 .svn/text-base/ 目錄內儲存了所有接受版本控管檔案的初始複本(pristine copy)。這表示你的工作複本至少會占用原本資料集的兩倍磁碟空間。此外,Subversion client 會採用 (目前無法調整的) 演算法來提交檔案:

  • 將檔案複製到 .svn/tmp/ (這會花一些時間,而暫存檔也會占用額外的磁碟空間)
  • 對暫存檔與初始複本 (pristine copy) 進行二進位的差異比對,若是新增加的檔案則會拿暫存檔與空檔比對。(這可能會花很長的時間運算,即使最終只有很少量的資料會傳送到網路的另一端)
  • 將差異送到伺服器,並將暫存檔移入 .svn/text-base/

因此雖然在理論上沒有檔案大小的限制,你還是得注意,當 client 程式在蹣跚處置較大檔案時,你得要耐著性子等待。然而,你可以放心的是,不像在 CVS,較大的檔案不會讓你的伺服器掛點,或影響到其他使用者。

因應那些不認得 copies/renames 動作的指令

在檔案或目錄複製或更名後,Subversion 儲存庫會追蹤歷程記錄。不幸的,在 Subversion 1.0 裡,善用這項特性的 client 端指令只有 svn log。許多其他指令 (例如 svn diff 及 svn cat) 應該要能自動追蹤更名歷程,但卻還沒這麼做。

面對這種情況,基本的因應之道是使用 'svn log -v' 指令找出舊版的檔案路徑。

例如,假設你在版號 200 中將 /trunk 複製到 /branches/mybranch,並在後續的版號中提交了對 /branches/mybranch/foo.c 的修改。現在你想比較該檔的 80 及 250 版號。

如果你有該分支的工作複本,並執行 svn diff -r80:250 foo.c,你會看到在版號 80 裡面並不存在 /branches/mybranch/foo.c 的錯誤訊息。補救方法是在你的分支或檔案上執行 svn log -v,以得知它在版號 200 之前稱為 /trunk/foo.c,接著就可以直接比較兩個 URL 了:

$ svn diff http://.../trunk/foo.c@80 http://.../branches/mybranch/foo.c@200

確定建立分支的時機

這是經常被爭論的話題,事實上這應該視軟體專案文化而定,而不是一套事先訂定的、放諸四海皆準的政策。我們將討論比較常見的三種型式:

從不分支的系統

(常用於還沒有可執行程式的初始專案)

  • 使用者直接將每天的變更提交到 /trunk 中。
  • 當某使用者開始提交一連串的複雜變更時,偶爾會造成 /trunk 的破壞 (無法編譯,或不能通過功能測試)。

優點:易於遵字的政策。新進開發人員進入門檻較低。沒有人需要學習如何操作分支及合併。

缺點:開發過程混亂,程式碼可能在任何時間產生不穩固的狀況。

附註:這種開發模式在 Subversion 中比 CVS 裡風險少一點點。因為 Subversion 的提交是單元式的 (atomic),即使當某人正在提交變更時,你也不可能僅取出 (checkout) 或更新 (update) 部分提交的變更。

總是分支的系統

(常用於傾向重度管理及監督的專案)

  • 每個使用者在他自己所建立的分支上進行開發工作。
  • 當實作完成後,某人 (原來的程式設計師,同儕,或經理) 複審所有私有分支的改變後,再將變更合併至 /trunk。

優點:可以保證 /trunk 在任何時間都相當穩固。

缺點:程式開發工作在此人為因素下與其他人分隔開來,可能產生更多不必要的合併衝突,而需要使用者進行許多額外的合併工作。

當需要時才分支的系統

(這是 Subversion 專案所採用的型式)

  • 使用者將每天的工作提交到 trunk 上
  • 規則 1:/trunk 必須在任何時間都能編譯,並通過回歸測試,違反此規則的提交者將在眾人面前無地自容。
  • 規則 2:單一的提交 (changeset) 不應太大,免得同儕難以複審。
  • 規則 3:若是規則 1 與規則 2 衝突 (例如,無法進行一連串的小提交同時保持 trunk 的穩固),那使用者就應建立一個分支,再於該分支上進行一連串的變更集小提交。這可以讓同儕順利進行複審,又保持 /trunk 的穩固性。

優點:可保證 /trunk 在任何時間都很穩固,也不用常常進行煩人的分支及合併。

缺點:會稍微增加使用者每天的工作負擔,他們在每次的提交前必須進行編譯及測試。

arrow
arrow
    全站熱搜

    Bluelove1968 發表在 痞客邦 留言(0) 人氣()