作者:Zoom.Quiet
本文包含了創(chuàng )建和使用Subversion 進(jìn)行軟件開(kāi)發(fā)的基本知識,為有志于使用Subversion 這一方便的版本管理工具來(lái)支持規范化團隊軟件開(kāi)發(fā)的程序員,在進(jìn)行分布式協(xié)同開(kāi)發(fā)時(shí),如何組織版本控制提供了基礎的建議和實(shí)用技巧;
當前最新版本是 1.5.5, SVN支持在各種操作系統中運行,安裝前請從官方網(wǎng)站下載對應版本; 本文將以 Ubuntu 系統為例進(jìn)行說(shuō)明.
一個(gè) 7.04 以上版本的Ubuntu 環(huán)境,有root 權限即可;
因為SVN 已經(jīng)包含在 Ubuntu 軟件倉庫中,安裝SVN 僅需一個(gè)命令:
$ sudo apt-get install subversion
如果系統報告了依賴(lài)關(guān)系的錯誤,請找出相應的軟件包并安裝它們。如果存在其它問(wèn)題,也請自行解決。如果您是再不能解決這些問(wèn)題,可以考慮通過(guò) Ubuntu 的網(wǎng)站、Wiki、論壇或郵件列表尋求支持。
SVN 可以提供多種協(xié)議的訪(fǎng)問(wèn)渠道,以下是模式列表:
| 模式 | 訪(fǎng)問(wèn)方法 |
|---|---|
| file:/// | 直接訪(fǎng)問(wèn)本地硬盤(pán)上文件倉庫 |
| http:// | 通過(guò) WebDAV 協(xié)議訪(fǎng)問(wèn)支持 Subversion 的 Apache 2 Web 服務(wù)器 |
| https:// | 類(lèi)似 http://,支持 SSL 加密 |
| svn:// | 通過(guò)自帶協(xié)議訪(fǎng)問(wèn) svnserve 服務(wù)器 |
| svn+ssh:// | 類(lèi)似 svn://,支持通過(guò) SSH 通道 |
$ svnadmin create /path/to/svn/myproj
$ svnserve -d -r /path/to/svn
# 本地訪(fǎng)問(wèn)
$ svn co svn://localhost/myproj
# 遠程訪(fǎng)問(wèn)
$ svn co svn://host.example.org/myproj
# 即刻下載,建立了本地工作復本,可以進(jìn)行協(xié)同開(kāi)發(fā)了
事實(shí)上在網(wǎng)絡(luò )中有很多SVN的免費空間可以使用,其中 http://code.google.com/intl/zh/ 是一個(gè)較輕便卻完備的的項目管理環(huán)境,只要注冊成功一個(gè)項目空間,就同時(shí)獲得了一個(gè)維基,一個(gè)Issue ~ 提案追蹤環(huán)境,和一個(gè)SVN倉庫;
# 項目成員可寫(xiě)訪(fǎng)問(wèn)命令是
$ svn co https://openbookproject.googlecode.com/svn/trunk/ openbookproject --username Zoom.Quiet
# 外部匿名讀者只訪(fǎng)問(wèn)命令是
$ svn co http://openbookproject.googlecode.com/svn/trunk/ openbookproject-read-only
如果沒(méi)有方便的主機資源,又想聯(lián)合分布在各地的朋友共同來(lái)進(jìn)行協(xié)同式軟件項目開(kāi)發(fā)的話(huà),可以考慮使用 Google 公司貢獻的這一服務(wù).
SVN 本身提供了豐富的管理工具, 在系統配置方面,僅僅有少量文件用以聲明關(guān)鍵信息.
在倉庫目錄的 conf 目錄中 svnserve.conf 是關(guān)鍵配置文件:
... [general] # 聲明匿名用戶(hù)權限 read|write anon-access = read # 聲明登錄用戶(hù)權限 read|write auth-access = write # 聲明登錄用戶(hù)口令信息文件 password-db = passwd.cfg # 聲明登錄用戶(hù)倉庫訪(fǎng)問(wèn)權限 authz-db = authz.cfg ...
配合svnserve.conf 的聲明, SVN 通過(guò)理解兩個(gè)文件來(lái)對倉庫的訪(fǎng)問(wèn)進(jìn)行控制:
聲明的口令文件,定義了權限用戶(hù)和口令:
[users] # 用戶(hù)名=口令 的格式來(lái)逐行聲明用戶(hù)賬號 woodpecker = 1q2w3e4r@woodpecker.org ...
聲明的認證文件,定義了權限用戶(hù)組和倉庫不同部分的訪(fǎng)問(wèn)控制:
[groups] # 聲明用戶(hù)組 repomana 包含了幾個(gè)用戶(hù) repomana = woodpecker,zoomq # 倉庫目錄權限聲明 [倉庫名:目錄名] 格式引導多個(gè)權限聲明 [woodpecker:/] # * 代表任何人 * = r # repoman 組成員可以讀寫(xiě) @repomana = rw [woodpecker:/foo] # 任何人可寫(xiě) * = rw # river 用戶(hù)只讀 river = r ...
作為標準意義上的版本管理系統,SVN 和其它任何版本管理系統日常使用并沒(méi)有什么巨大的不同,是一個(gè)非常容易上手的工具系統;
以命令行形式說(shuō)明日常通過(guò)SVN 進(jìn)行協(xié)同開(kāi)發(fā)時(shí)最常用的操作:
$ svn up
$ svn add ~ 增補文件/目錄
$ svn del ~ 刪除文件/目錄
$ svn cp ~ 復制文件/目錄
$ svn mv ~ 移動(dòng)文件/目錄
--help 獲得充分的指示,例如:
$ svn mv --help
move (mv, rename, ren): 在工作副本或版本庫中移動(dòng)或改名文件或目錄。
用法: move SRC... DST
當移動(dòng)多個(gè)源時(shí),它們作為 DST 的子節點(diǎn)增加,DST 必須是目錄。
注意: 本子命令等同于先 “copy”,然后 “delete”。
注意: 此命令中 --revision 選項沒(méi)有作用,已經(jīng)淘汰。
SRC 可同時(shí)為工作副本(WC) 路徑或 URL:
WC -> WC : 移動(dòng)并加入新增調度 (連同歷史記錄)
URL -> URL : 完全是服務(wù)器端更名。
所有 SRC 必須是同一類(lèi)型。
有效選項:
-r [--revision] ARG : ARG (一些命令也接受ARG1:ARG2范圍)
版本參數可以是如下之一:
NUMBER 版本號
'{' DATE '}' 在指定時(shí)間以后的版本
'HEAD' 版本庫中的最新版本
'BASE' 工作副本的基線(xiàn)版本
'COMMITTED' 最后提交或基線(xiàn)之前
'PREV' COMMITTED的前一版本
-q [--quiet] : 不打印信息,或只打印概要信息
--force : 強制操作運行
--parents : 創(chuàng )建中間目錄
-m [--message] ARG : 指定日志信息ARG
-F [--file] ARG : 從文件ARG讀取日志信息
--force-log : 強制校驗日志信息資源
--editor-cmd ARG : 使用 ARG 作為外部編輯器
--encoding ARG : 將ARG的值視為字符編碼
--with-revprop ARG : 在新版本設置版本屬性 ARG
使用格式 name[=value]
$ svn revert
revert: 將工作副本文件恢復到原始版本(恢復大部份的本地修改)。
用法: revert PATH...
注意: 本子命令不會(huì )訪(fǎng)問(wèn)網(wǎng)絡(luò ),它解除任何沖突的狀態(tài)。
但是,它不恢復被刪除的目錄。
有效選項:
--targets ARG : 傳遞文件 ARG 內容為附件參數
-R [--recursive] : 向下遞歸,與 --depth=infinity 相同
--depth ARG : 受深度參數 ARG(“empty”,“files”,“immediates”,或“infinity”) 約束的操作
-q [--quiet] : 不打印信息,或只打印概要信息
--changelist ARG : 只能對修改列表 ARG 成員操作
[aliases: --cl]
$ svn resolved
resolved: 刪除工作副本中目錄或文件的“沖突”狀態(tài)。
用法: resolved PATH...
注意: 本子命令不會(huì )依語(yǔ)法來(lái)解決沖突或是刪除沖突標記;它只是刪除沖突相關(guān)的
附加文件,讓 PATH 可以被再次提交。它已經(jīng)過(guò)時(shí),被
“svn resolve --accept working”取代。
有效選項:
--targets ARG : 傳遞文件 ARG 內容為附件參數
-R [--recursive] : 向下遞歸,與 --depth=infinity 相同
--depth ARG : 受深度參數 ARG(“empty”,“files”,“immediates”,或“infinity”) 約束的操作
-q [--quiet] : 不打印信息,或只打印概要信息
$ svn up
C sandwich.txt
Updated to revision 2.
$ ls -1
sandwich.txt
sandwich.txt.mine
sandwich.txt.r1
sandwich.txt.r2
sandwich.txt,直到你解決沖突,可選的處置是:
svn revert <filename>來(lái)放棄所有的本地修改
<filename>.r* 代表的是文件的第幾個(gè)版本
<filename>.mine 代表的是本地我的文件版本
<filename> 是包含沖突標識的提示文件
$ svn ci -m "提交理由"
然后,就是以上過(guò)程的不斷循環(huán)
特別的,對于從CVS系統遷移過(guò)來(lái)的用戶(hù),需要提升一些關(guān)鍵概念,來(lái)更好的使用 SVN:
“foo.c在修訂版本5出現”。同樣,我們在假定文件的進(jìn)展時(shí)也要小心,在CVS,文件foo.c的修訂版本5和6一定是不同的,在Subversion,foo.c可能在修訂版本5和6之間沒(méi)有改變。
svn add和svn delete現在也工作在目錄上了,就像在文件上一樣,還有svn copy和svn move也一樣;然而,這些命令不會(huì )導致版本庫即時(shí)的變化,相反,工作的項目只是“預定要”添加和刪除,在運行svn commit之前沒(méi)有版本庫的修改
cvs status和cvs update之間的混亂。
cvs status命令有兩個(gè)目的:
cvs update或cvs -n update來(lái)快速查看區別,如果用戶(hù)忘記使用-n選項,副作用就是將還沒(méi)有準備好處理的版本庫修改合并到工作拷貝。
svn status的輸出使之同時(shí)滿(mǎn)足閱讀和解析的需要來(lái)努力消除這種混亂,同樣,svn update只會(huì )打印將要更新的文件信息,而不是本地修改
status (stat, st): 顯示工作副本中目錄與文件的狀態(tài)
用法: status [PATH...]
未指定參數時(shí),只顯示本地修改的條目(沒(méi)有網(wǎng)絡(luò )訪(fǎng)問(wèn))。
使用 -q 時(shí),只顯示本地修改條目的摘要信息。
使用 -u 時(shí),增加工作版本和服務(wù)器上版本過(guò)期信息。
使用 -v 時(shí),顯示每個(gè)條目的完整版本信息。
輸出的前六欄各占一個(gè)字符寬度:
第一欄: 表示一個(gè)項目是增加、刪除,還是修改
“ ” 無(wú)修改
“A” 增加
“C” 沖突
“D” 刪除
“I” 忽略
“M” 改變
“R” 替換
“X” 未納入版本控制,但被外部項目所用
“?” 未納入版本控制
“!” 該項目已遺失(被非 svn 命令刪除)或不完整
“~” 版本控制下的項目與其它類(lèi)型的項目重名
第二欄: 顯示目錄或文件的屬性狀態(tài)
“ ” 無(wú)修改
“C” 沖突
“M” 改變
第三欄: 工作副本目錄是否被鎖定
“ ” 未鎖定
“L” 鎖定
第四欄: 已調度的提交是否包含副本歷史
“ ” 沒(méi)有包含
“+” 包含
第五欄: 該條目相對其父目錄是否已切換
“ ” 正常
“S” 已切換
第六欄: 版本庫鎖定標記
(沒(méi)有 -u)
“ ” 沒(méi)有鎖定標記
“K” 存在鎖定標記
(使用 -u)
“ ” 沒(méi)有在版本庫中鎖定,沒(méi)有鎖定標記
“K” 在版本庫中被鎖定,存在鎖定標記
“O” 在版本庫中被鎖定,鎖定標記在一些其他工作副本中
“T” 在版本庫中被鎖定,存在鎖定標記但已被竊取
“B” 沒(méi)有在版本庫中被鎖定,存在鎖定標記但已被終止
是否過(guò)期的信息出現的位置是第八欄(與 -u 并用時(shí)):
“*” 服務(wù)器上有更新版本
“ ” 工作副本是最新版的
剩余的欄位皆為變動(dòng)寬度,并以空白隔開(kāi):
工作版本號(使用 -u 或 -v 時(shí))
最后提交的版本與最后提交的作者(使用 -v 時(shí))
工作副本路徑總是最后一欄,所以它可以包含空白字符。
范例輸出:
svn status wc
M wc/bar.c
A + wc/qax.c
svn status -u wc
M 965 wc/bar.c
* 965 wc/foo.c
A + 965 wc/qax.c
Status against revision: 981
svn status --show-updates --verbose wc
M 965 938 kfogel wc/bar.c
* 965 922 sussman wc/foo.c
A + 965 687 joe wc/qax.c
965 687 joe wc/zig.c
Status against revision: 981
有效選項:
-u [--show-updates] : 顯示更新信息
-v [--verbose] : 打印附加信息
-N [--non-recursive] : 過(guò)時(shí);嘗試 --depth=files 或 --depth=immediates
--depth ARG : 受深度參數 ARG(“empty”,“files”,“immediates”,或“infinity”) 約束的操作
-q [--quiet] : 不打印信息,或只打印概要信息
--no-ignore : 忽略默認值和 svn:ignore 屬性
--incremental : 給予適合串聯(lián)的輸出
--xml : 輸出為 XML
--ignore-externals : 忽略外部項目
--changelist ARG : 只能對修改列表 ARG 成員操作
[aliases: --cl]
分支自然可見(jiàn)了!而標簽不必要了!
$ svn cp trunk branches/my-proj-branch_0.1
changeset(修訂集)來(lái)使用的標簽 在SVN 中,版本號天然就包含了這一特性, 完全可以用版本號來(lái)當 標簽用!
因為Subversion把分支和標簽看作普通目錄看待,一直要記住檢出項目的trunk(http://svn.example.com/repos/calc/trunk/),
而不是項目本身的(http://svn.example.com/repos/calc/)。
如果你錯誤的檢出了項目本身,你會(huì )緊張的發(fā)現你的項目拷貝包含了所有的分支和標簽
SVN 有豐富的客戶(hù)端軟件可以選擇,一般命令行內置工具已經(jīng)足夠好用,但是對習慣窗口界面的人,SVN 也有很多選擇,其中最穩定和友好的是官方社區創(chuàng )建的:
建議Windows 中的用戶(hù)下載體驗;
SVN 作為成熟的版本管理系統,可以支持各種級別的開(kāi)發(fā)支持; 當面對大型復雜系統開(kāi)發(fā)時(shí),作為基礎配置管理支持系統,必須擁有一些高級功能來(lái)支撐復雜業(yè)務(wù),這里介紹幾方面常用知識;
整個(gè)過(guò)程隨著(zhù)軟件的成熟不斷重復:
$ cd trunk-working-copy
$ svn update
At revision 1910.
$ svn merge http://svn.example.com/repos/calc/trunk@1910 http://svn.example.com/repos/calc/branches/mybranch@1910
U real.c
U integer.c
A newdirectory
A newdirectory/newfile
…
通過(guò)比較HEAD修訂版本的主干和HEAD修訂版本的分支,你確定了只在分支上的增量信息,兩條開(kāi)發(fā)線(xiàn)都有了分枝的修改。
和CVS 類(lèi)似SVN 同樣為自動(dòng)化事務(wù)響應開(kāi)辟有"HOOKS"~鉤子腳本支持;只是更加精簡(jiǎn)和規范化了;
一般提供9類(lèi)標準鉤子模板:
$ ls repos/hooks/ post-commit.tmpl post-unlock.tmpl pre-revprop-change.tmpl post-lock.tmpl pre-commit.tmpl pre-unlock.tmpl post-revprop-change.tmpl pre-lock.tmpl start-commit.tmpl
分別響應核心的四類(lèi)操作:
| HOOK | 觸發(fā)事件 | 參數 |
|---|---|---|
| start-commit | 提交事務(wù)產(chǎn)生前 | REPOS-PATH:到版本庫的路徑;USER:要進(jìn)行提交的用戶(hù)名 |
| pre-commit | 事務(wù)完成提交之前 | REPOS-PATH:版本庫的路徑;TXN-NAME正在提交的事務(wù)名稱(chēng) |
| post-commit | 事務(wù)完成后 | REPOS-PATH:到版本庫的路徑;REV:被創(chuàng )建的新的修訂版本號 |
| pre-revprop-change | 修訂版本屬性變更前 | REPOS-PATH:到版本庫的路徑;REVISION:要修改屬性的修訂版本;USER:經(jīng)過(guò)認證的用戶(hù)名;ACTION:屬性自身的名字 |
| post-revprop-change | 修訂版本屬性被改變之后 | REPOS-PATH:到版本庫的路徑;REVISION:屬性存在的修訂版本;USER:經(jīng)過(guò)校驗的產(chǎn)生變化的用戶(hù)名;ACTION:和屬性自身的名字 |
| pre-lock | 嘗試鎖定文件時(shí) | REPOS-PATH:到版本庫的路徑;PATH:鎖定的路徑;USER:企圖執行鎖定的用戶(hù) |
| post-lock | 路徑被鎖定后執行 | REPOS-PATH:到版本庫的路徑;USER:企圖執行鎖定的用戶(hù) |
| pre-unlock | 企圖刪除一個(gè)文件上的鉤子時(shí) | REPOS-PATH:到版本庫的路徑;PATH:鎖定的路徑;USER:企圖解鎖的用戶(hù) |
| post-unlock | 路徑被解鎖后 | REPOS-PATH:到版本庫的路徑;USER:企圖解鎖的用戶(hù) |
pre-commit鉤子的事務(wù),在不滿(mǎn)足要求時(shí)拒絕提交。
舉個(gè)實(shí)用的HOOKS 腳本實(shí)例:
pre-commit.tmpl 重命名為:pre-commit 并修訂為以下內容:
#!/bin/sh
# PRE-COMMIT HOOK
REPOS="$1"
TXN="$2"
SVNLOOK=/usr/local/bin/svnlook
$SVNLOOK log -t "$TXN" "$REPOS" | grep "[a-zA-Z0-9]" > /dev/null
if [ $? != 0 ]; then
echo "$TXN $REPOS" 1>&2
echo "Alert! Commit message may not be empty." 1>&2
exit 1
fi
exit 0
"Alert! Commit message may not be empty."
SVN作為基礎配置管理支撐系統,可以輕快的完成版本管理的全方位支持了,而且,進(jìn)一步的配合Trac 可以完成項目管理的大部分流程支持!
Trac 是種輕型全功能項目管理環(huán)境,主要特性有:
詳細的敬請期待哲思手冊相關(guān)文章;
PS:
Trac中文化項目長(cháng)期由 Zoom.Quiet 團隊支持,推薦體驗;
聯(lián)系客服