Subversion 系統(tǒng)
多年來,并發(fā)版本系統(tǒng)(CVS)一直是在Linux上管理代碼或者文本的標(biāo)準(zhǔn)。作為基于RCS上建立但卻允許多用戶協(xié)作的系統(tǒng)而言,CVS記錄所有文件的修改信息。這對(duì)于程序開發(fā)者、網(wǎng)絡(luò)設(shè)計(jì)者和系統(tǒng)管理員而言,是非常有用的。 然而,CVS逐漸顯示出它的衰老,出現(xiàn)了相似的源代碼管理軟件。然而大多這種東西都是以牟利為主要目的的。 Subversion就是一種相對(duì)新鮮的源代碼管理系統(tǒng)。雖然事實(shí)上它還在不斷的反展之中,但是Subversion已經(jīng)是一個(gè)非常穩(wěn)定而且成熟的產(chǎn)品。它是一個(gè)全新的系統(tǒng),其功能可以和CVS媲美,同時(shí),它要比CVS更直觀,更容易操作。本文就Subversion的安裝和一些特殊功能作一個(gè)介紹。 安裝服務(wù)器端 下載Apache和SVN源碼包 從官方網(wǎng)站臺(tái)下載httpd-2.0.52.tar.gz,subversion-1.1.1.tar.gz (因?yàn)閞edhat 9默認(rèn)安裝的Apache沒有并包含--enable-so選項(xiàng),所以無法產(chǎn)生mod_dav_svn.沒有這個(gè)模塊,SVN就無法采用http方式運(yùn)行,所以必須重新編譯新的Apache) 以root身份執(zhí)行: #tar zxvf httpd-2.0.52.tar.gz #cd httpd-2.0.52 #./configure --enable-dav --enable-so --enable-maintainer-mode #make #make install 此時(shí)會(huì)產(chǎn)生/usr/local/apache2目錄,接著執(zhí)行: #tar zxvf subversion-1.1.1.tar.gz #./configure --with-apxs=/usr/local/apache2/bin/apxs # rm /usr/local/lib/libsvn* # make clean && make && make install 此時(shí)會(huì)自動(dòng)在/usr/local/apache2/conf/httpd.conf添加 LoadModule dav_svn_module ?modules/mod_dav_svn.so 安裝完成后,運(yùn)行svnserver --version確認(rèn)版本為1.1.1。 SVN服務(wù)器安裝結(jié)束. 安裝客戶機(jī)端 window客戶機(jī): 直接安裝TortoiseSVN-1.1.1-UNICODE_svn-1.1.1.msi,方法同一般軟件安裝相同。 Linux客戶機(jī): 方法輿安裝服務(wù)器相同。 (注意redhat 9默認(rèn)安裝的SVN版本為0.17.1,它的客戶端命令svn無法輿新的SVN服務(wù)器通訊,必須重新安裝) 建立倉(cāng)庫(kù)Repository Subversion 的檔案庫(kù)是個(gè)中央倉(cāng)儲(chǔ), 用來存放任意數(shù)量項(xiàng)目的受版本控管資料,建立方法很簡(jiǎn)單 #svnadmin create path/to/repos 舉個(gè)例子: #svnadmin create /home/mysvn #chown –R nobody /home/mysvn 運(yùn)行服務(wù)器 Subversion服務(wù)器有兩種運(yùn)行方式,一是可以作為Apache 2.0的一個(gè)模塊, 以WebDAV/DeltaV協(xié)議與外界連通;另外,也可使用Subversion 自帶的小型服務(wù)器程序svnserve。該程序使用的是自帶的通訊協(xié)議,可以很容易地透過SSH以 以http方式運(yùn)行 在/usr/local/apache2/conf/httpd.conf中加入: <Location /svn/repository> ?DAV svn ?SVNPath /home/mysvn </Location> 在服務(wù)器的瀏覽器中輸入網(wǎng)址: http://localhost/svn/repository/ 這時(shí)候,你會(huì)看到這樣的顯示: 這表明服務(wù)器已經(jīng)以http方式正常運(yùn)行了. 以svnserve方式運(yùn)行 這種方式的運(yùn)行又可以分為以下兩種(這和vsftp有些相似) 1) standalone mode 直接運(yùn)行 #svnserve –d 運(yùn)行 lsof -i :3690可以看到SVN服務(wù)器已經(jīng)在運(yùn)行 2) xinetd mode 在/etc/xinetd.d/下生成svnserve文件,內(nèi)容如下 service svnserve { disable = no socket_type ? ? ? ? ? ? = stream protocol ? ? ? ? ? ? ? ? = tcp wait ? ? ? ? ? ? ? ? ? ?= no user ? ? ? ? ? ? ? ? ? ?= apache server ? ? ? ? ? ? ? ? ?= /usr/local/bin/svnserve server_args ? ? ? ? ? ? = -i } 編輯 /etc/services 檔,加入底下兩行: svnserve ? ? ? ?3690/tcp ? ? ? ? ? ? ? ? ? ? ? ?# Subversion svnserve svnserve ? ? ? ?3690/udp ? ? ? ? ? ? ? ? ? ? ? ?# Subversion svnserve 重啟xinetd服務(wù),運(yùn)行 lsof -i :3690可以看到SVN服務(wù)器已經(jīng)在運(yùn)行 客戶機(jī)訪問 客戶機(jī)的訪問方法輿服務(wù)器的運(yùn)行方式有直接關(guān)系 window客戶機(jī): 1) 服務(wù)器以http方式運(yùn)行 安裝完TortoiseSVN-1.1.1-UNICODE_svn-1.1.1.msi后,在你想工作的目錄下點(diǎn)擊右鍵,執(zhí)行checkout,按上圖輸入即可。 2) 服務(wù)器以svnserve方式運(yùn)行 同上的區(qū)別只是URL of repository變?yōu)?svn://svn服務(wù)器ip/home/mysvn 或者 svn+ssh://svn服務(wù)器ip/home/mysvn (注意不是//svn服務(wù)器ip//svn/repository) linux客戶機(jī): 1) 服務(wù)器以http方式運(yùn)行 執(zhí)行 #svn checkout http: //svn服務(wù)器ip/svn/repository 2) 服務(wù)器以svnserve方式運(yùn)行 執(zhí)行 #svn checkout svn://svn服務(wù)器ip/home/mysvn 或者 #svn checkout svn+ssh://svn服務(wù)器ip/home/mysvn 客戶認(rèn)證機(jī)制 這輿服務(wù)器的運(yùn)行方式有關(guān) 服務(wù)器以http方式運(yùn)行 比如我們想給 Sally 與 Harry 送交存取檔案庫(kù)的權(quán)限. 首先, 我們必須把它們加入到密碼檔案. # ### 第一次: 以 -c 建立檔案 # htpasswd -c /etc/svn-auth-file harry New password: ***** Re-type new password: ***** Adding password for user harry # htpasswd /etc/svn-auth-file sally New password: ******* Re-type new password: ******* Adding password for user sally # 接著,在/usr/local/apache2/conf/httpd.conf的加入: <Location /svn/repository > ?DAV svn ?SVNPath /home/mycvs ?AuthType Basic ?AuthName "Subversion repository" ?AuthUserFile /etc/svn-auth-file Require valid-user </Location> 重新激活 Apache后,如果有人要訪問SVN服務(wù)器,系統(tǒng)會(huì)要求他輸入用戶名和密碼。 只有輸入Sally 或Harry的用戶名和相應(yīng)的密碼,才可以對(duì)檔案庫(kù)進(jìn)行修改和訪問 服務(wù)器以svnserve方式運(yùn)行 默認(rèn)下客戶可以以匿名方式通過svn://方式任意訪問檔案庫(kù),為了限制其權(quán)限,比如只允許讀操作,可以通過修改檔案庫(kù)conf子目錄中的svnseve.conf文件來實(shí)現(xiàn)。 #vi /home/mysvn/conf/svnseve.conf 修改[general]字段下內(nèi)容為: anon-access = read 如果設(shè)為anon-access = none,則匿名用戶不可以通過svn://方式訪問檔案庫(kù) 為了實(shí)現(xiàn)用戶認(rèn)證,我們一般采用svn+ssh://訪問機(jī)制。 首先在svnseve.conf文件設(shè)置anon-access = none禁止匿名用戶通過svn://方式訪問檔案庫(kù),然后在其后加入 auth-access = write auth-access 是限制有援權(quán)的使用者(使用svn+ssh:// 來登入) 的存取權(quán)限,我們?cè)O(shè)為是可以讀寫。 當(dāng)用戶通過svn+ssh://訪問時(shí),服務(wù)器會(huì)自動(dòng)激活ssh認(rèn)證機(jī)制,要求用戶輸入密碼,對(duì)于window用戶來說還需要安裝第三方軟件openssh,才可以采用這種機(jī)制 Hook scripts 掛勾 (hook) 是改動(dòng)檔案庫(kù)時(shí)所觸發(fā)的程序, 比如當(dāng)你提交更動(dòng)前,會(huì)先觸發(fā)pre-commit,提交更動(dòng)后,則會(huì)觸發(fā)post-commit,我們可以利用hook來實(shí)現(xiàn)一些自動(dòng)控制。檔案庫(kù)的hook 子目錄中, 預(yù)設(shè)是放置各個(gè)檔案庫(kù)掛勾的模板: post-commit.tmpl ? ? ? ? ? pre-revprop-change.tmpl post-revprop-change.tmpl ? start-commit.tmpl pre-commit.tmpl ? ? ? ? 如果要使用這些hook,就必須把它的后綴名.tmpl去掉,拷貝為 post-commit ? ? ? ? ? pre-revprop-change post-revprop-change ? start-commit pre-commit 這里主要介紹pre-commit和post-commit(事實(shí)上它們就是在特定的情況下被觸發(fā)的普通的shell程序,至于shell的內(nèi)容由用戶自己隨意編寫,但是要保證名稱不能改動(dòng)) pre-commit 本掛勾執(zhí)行的時(shí)間為異動(dòng)完成之后, 送交之前.檔案庫(kù)會(huì)傳遞兩個(gè)自變量給這個(gè)程序: 檔案庫(kù)的路徑, 以及準(zhǔn)備送交的異動(dòng)名稱. 如果程序傳回一個(gè)非零的結(jié)束值, 送交會(huì)被中止, 而異動(dòng)會(huì)被刪除. 如何應(yīng)用pre-commit我們不妨舉個(gè)例子: 假如有一個(gè)項(xiàng)目由Mail Team,Login Team和PHP Team三個(gè)Team共同通過SVN系統(tǒng)開發(fā)完成。當(dāng)項(xiàng)目準(zhǔn)備發(fā)布的時(shí)候,PM人員發(fā)現(xiàn)Mail功能方面存在一些 bug,需要Mail Team去修改,為了防止其它Team的人員修改系統(tǒng),我們可以在任何改動(dòng)檔案庫(kù)的企圖之前用pre-commit去檢查log message信息,(因?yàn)槿魏胃鼊?dòng)檔案庫(kù)的操作都必須提供log message信息,PM可以事先輿Mail Team約定好一個(gè)log message),如果輿pre-commit中設(shè)定的log message不相符,則不能提交更動(dòng)。 pre-commit源程序如下: #!/bin/sh REPOS="$1" TXN="$2" SVNLOOK=/usr/local/bin/svnlook $SVNLOOK log -t "$TXN" "$REPOS" | \ ? grep –w "bug1234" > /dev/null || exit 1 exit 0 本例中的log message為”bug1234”,任何人想要提交更動(dòng)就必須用 –m “bug1234”參數(shù),采用-m “bug123”,-m “bug12345”都會(huì)提交失敗。 post-commit 本掛勾執(zhí)行的時(shí)間是在異動(dòng)送交, 新修訂版被建立之后. 大多數(shù)的人用這個(gè)掛勾來寄出關(guān)于本次送交的電子郵件, 或是建立檔案庫(kù)的備份. 檔案庫(kù)會(huì)傳遞兩個(gè)自變量給這個(gè)程序: 檔案庫(kù)的路徑, 以及新建立的修訂版號(hào). 本程序的結(jié)束碼會(huì)被忽略. Subversion 源碼樹的 tools/hook-script 目錄中包含了一個(gè) commit-email.pl 命令,可以用來寄送包含描述指定送交的電子郵件. 這個(gè)郵件包含了更動(dòng)路徑列表, 該送交所對(duì)應(yīng)的記錄訊息, 使用者, 送交的日期,以及一個(gè)以 GNU diff 樣式表示的本次更動(dòng)差異. 我們可以將這個(gè)程序輿post-commit這個(gè)hook搭配起來使用來實(shí)現(xiàn)檔案庫(kù)更動(dòng)后自動(dòng)mail給相關(guān)人員的功能。 post-commit源程序如下: #!/bin/sh REPOS="$1" REV="$2" commit-email.pl "$REPOS" "$REV" PM@yourdomain.com ##需要指明commit-email.pl的絕對(duì)路徑 特殊性質(zhì) 除了對(duì)你的目錄與檔案進(jìn)行版本控制之外, Subversion 還提供了一個(gè)接口, 可用來新增, 修改, 以及移除已納入版本控制的目錄與檔案的版本控制描述資料. 我們稱這個(gè)描述資料為性質(zhì),在這里我主要介紹以下幾個(gè)比較重要的特殊性質(zhì) svn:mime-type svn:mime-type 性質(zhì)在 Subversion 中有很多作用. 除了作為儲(chǔ)存檔案的多用途網(wǎng)際網(wǎng)絡(luò)郵件延伸語法 (MIME) 分類之外, 這個(gè)性質(zhì)的內(nèi)容還會(huì)決定幾項(xiàng) Subversion 的行為特征. 舉個(gè)例子, 如果 svn:mime-type 性質(zhì)設(shè)為文字的 MIME 類別 , Subversion 會(huì)假設(shè)該檔的內(nèi)容是二進(jìn)制(也就是人類看不懂的資料). Subversion 提供的功能中, 其中一項(xiàng)是在從服務(wù)器收到工作檔的更新中, 依文字內(nèi)容與文字列進(jìn)行合并. 但是對(duì)含有二進(jìn)制資料的檔案, 根本就沒有 “文字列” 的概念. 因此, Subversion 對(duì)這些檔案在更新時(shí), 不會(huì)試著進(jìn)行內(nèi)文合并. 它改用另一種方式。 一般來說Subversion 在執(zhí)行 svn import 與 svn add 子命令時(shí), 會(huì)使用二進(jìn)制偵測(cè)運(yùn)算法的方式來協(xié)助使用者.但是如果 Subversion 猜錯(cuò)了, 或是你希望將 svn:mime-type 設(shè)定成更為明確的值(可能是 image/png)你都可以移除或是手動(dòng)編輯這個(gè)性質(zhì). svn:ignore svn:ignore 性質(zhì)包含了檔案樣式的列表, Subversion 處理時(shí)會(huì)忽略. 它可以與執(zhí)行時(shí)期設(shè)定的 global-ignores 選項(xiàng)一起工作, 以便在類似 svn status 的命令中過濾掉未納入版本控制的目錄與檔案. 我們知道新增的文件和目錄必須透過 svn add 命令, 才會(huì)被納入 Subversion 的管理. svn status 命令會(huì)將工作復(fù)本中未納入版控制目錄與檔案顯示出來. $ svn status calc M ? ? calc/button.c ? ? ? ?calc/calculator ? ? ? ?calc/data.c ? ? ? ?calc/debug_log ? ? ? ?calc/debug_log.1 在這個(gè)范例中, 用?標(biāo)注出來的文件就是未納入版控制的檔案.如果你不想每次執(zhí)行 svn status 時(shí), 都看到這些檔案, 那幺svn:ignore 性質(zhì)就是解決方案。你可以透過 svn propedit svn:ignore calc 對(duì) calc 目錄加上一些忽略樣式. 舉個(gè)例子,將以下的值作為 svn:ignore 性質(zhì)的新內(nèi)容: calculator debug_log* 加上這個(gè)性質(zhì)后再執(zhí)行你的 svn status 輸出便會(huì)不同: $ svn status M ? ? calc M ? ? calc/button.c ? ? ? ?calc/data.c 現(xiàn)在, 所有不想看到的東西都從輸出中消失了! svn:keywords Subversion 具有取代關(guān)鍵詞(有關(guān)納入版本控制檔案的有用信息)進(jìn)入檔案內(nèi)容的功能. 舉個(gè)例子, 假設(shè)你有個(gè)文件, 想要在里面顯示最近一次修改的日期. 你可以把這個(gè)負(fù)擔(dān)加諸文件的作者身上, 讓他們每一次送交更動(dòng)之前, 順便添加最近一次修改日期的部份. 但是遲早有人會(huì)忘記這件事. 換個(gè)方式, 只要叫 Subversion 對(duì) LastChangedDate 關(guān)鍵詞進(jìn)行關(guān)鍵詞取代即可. Subversion 定義了可用來進(jìn)行取代的關(guān)鍵詞列表. 這個(gè)列表包含了以下五個(gè)關(guān)鍵詞: LastChangedDate LastChangedRevision LastChangedBy HeadURL Id 如果只把關(guān)鍵詞定位錨加進(jìn)檔案里的話, 什幺事也不會(huì)發(fā)生.要告訴 Subversion 是否該對(duì)某一個(gè)檔案進(jìn)行關(guān)鍵詞取代,得使用svn:keywords這個(gè)性質(zhì)。當(dāng)它被設(shè)定時(shí), 它會(huì)控制該檔案哪個(gè)關(guān)鍵詞應(yīng)該被取代. 舉個(gè)例子, 假設(shè)你有一個(gè)納入版本控制的檔案, 名為 weather.txt, 看起來像這樣: Here is the latest report from the front lines. $LastChangedDate$ $Rev$ Cumulus clouds are appearing more frequently as summer approaches. 如果沒有設(shè)定該檔案的 svn:keywords 性質(zhì), Subversion 什幺事也不會(huì)作. 讓我們開啟關(guān)鍵詞 LastChangedDate 的內(nèi)容取代. $ svn propset svn:keywords "LastChangedDate Author" weather.txt property `svn:keywords' set on 'weather.txt' $ 在你送交了這個(gè)性質(zhì)更動(dòng)之后, Subversion 會(huì)顯示為: Here is the latest report from the front lines. $LastChangedDate: 2002-07-22 21:42:37 -0700 (Mon, 22 Jul 2002) $ $Rev$ Cumulus clouds are appearing more frequently as summer approaches. 這樣不管誰提交這個(gè)文件,都會(huì)在里面顯示最近一次修改的日期。 svn:eol-style 除非另外指定版本控制檔案的 svn:mime-type 性質(zhì), Subversion 會(huì)假設(shè)檔案包含人類可讀的資料.這對(duì)于列尾符號(hào) (EOL) 是很不幸地, 因?yàn)椴煌牟僮飨到y(tǒng)會(huì)使用不同的符號(hào)來表示一列的結(jié)尾. 舉個(gè)例子, 一般用在 Windows 平臺(tái)上的列尾符號(hào)是兩個(gè) ASCII 控制字符 :返回字符 (CR) 與換行字符 (LF). 但是 Unix 軟件就只使用 LF 字符來表示一列的結(jié)尾.這樣以來window客戶提交的檔案中的CR 字符在 linux客戶端會(huì)顯示成 ^M, 而linux客戶提交的檔案中CR 字符在 Windows 客戶端會(huì)被忽略。結(jié)果將檔案里的所有文字列合并成一個(gè)超長(zhǎng)的文字列, 這是因?yàn)闆]有返回CRLF字符組合的存在來表示一個(gè)換行。 解決的方法是 svn:eol-style 性質(zhì). 當(dāng)這個(gè)性質(zhì)設(shè)定為native時(shí), Subversion 會(huì)根據(jù)系統(tǒng)的類型來決定是否對(duì)該檔案的結(jié)尾進(jìn)行自動(dòng)處理。. svn:externals 有的時(shí)候, 一個(gè)工作復(fù)本可能包含了數(shù)個(gè)不同來源的工作復(fù)本. 舉個(gè)例子, 你可能想要有數(shù)個(gè)不同的目錄, 各來自不同的檔案庫(kù).我們可以通過svn:externals 性質(zhì)來宣告這一對(duì)對(duì)應(yīng)關(guān)系。內(nèi)容是子目錄對(duì)應(yīng)至 Subversion 檔案庫(kù) URL 的多行表格. $ svn propget svn:externals calc third-party/sounds ? ? ? ? ?http://sounds.red-bean.com/repos third-party/skins ? ? ? ? ? http://skins.red-bean.com/repositories/skinproj third-party/skins/toolkit ? http://svn.red-bean.com/repos/skin-maker 當(dāng)有人取出 calc 目錄的工作復(fù)本, Subversion 還會(huì)繼續(xù)取出在外部定義里的項(xiàng)目. $ svn checkout http://svn.example.com/repos/calc A ?calc A ?calc/Makefile A ?calc/integer.c A ?calc/button.c Checked out revision 148. Fetching external item into calc/third-party/sounds A ?calc/third-party/sounds/ding.ogg A ?calc/third-party/sounds/dong.ogg A ?calc/third-party/sounds/clang.ogg Checked out revision 14. Fetching external item into calc/third-party/skins … 小結(jié) Subversion有一份很好的文檔——《Version Control with Subversion》(http://svnbook.red-bean.com/)。它提供了有關(guān)Subversion的各方面內(nèi)容,如使用、管理和開發(fā)等。 經(jīng)過數(shù)年的開發(fā),以替代CVS為目標(biāo)的Subversion,相信以其強(qiáng)大的功能,對(duì)CVS良好的繼承性,一定會(huì)有很好的發(fā)展 |