`
dalezhu
  • 浏览: 203552 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Linux CVS 教學(转)

    博客分类:
  • OS
阅读更多

1. 簡介

教學大綱

這分文件包含兩個部份。首先是一般使用者如使用 CVS。例如如何透過 CVS 取得最新的原始碼,並且更新到最近的檔案。另一部份就是如何用 CVS 來共同開發程式,包括修改、新增、移除 CVS 上的檔案。建議您先閱讀第一部份,然後再接著讀第二部份。如果您之前已經有一些 CVS 的使用經驗,但是您第一次以 CVS 來開發程式,您可以在第二部份找到所有的資料,但或許您可以看看的一部份來複習。

CVS是什麼?他是作什麼用的?

CVS 是一個主從架構的系統,讓發展者可以藉它存放他們的專案在叫做儲藏庫(repository) 的地方。發展者可以藉著 CVS 客戶端工具來修改儲藏庫內的檔案,CVS 會追蹤每個檔案的改變,並且建立這個專案完整的發展過程。發展者可以取得專案中某個檔案的較舊的版本,看修改紀錄,或是作其他有用的工作。

CVS 的作用

許多的自由軟體有他們自己的 CVS 伺服器,當作程式發展者主要儲存的地方。發展者常常會每天對程式作一些改進,而且他們通常是散佈在世界各地,因此 CVS 提供一個讓所有人聯繫起來的機制。CVS 建立一種團隊的聯繫讓開發人員改進程式碼而不會蓋掉其他人的修改,也不會遺失重要的資料或是重要的更新。

CVS -- 最新的原始碼

當程式發展差不多的時候,他們就會把 CVS 上目前的檔案壓縮成 .tar.gz 然後以新的版本發表。然而,因為各種原因,最近的發表版本未必是最新的檔案。在這分教學的第一部份將會教您如何用 CVS 取得最新的程式碼來使用。

安裝 CVS

要安裝 CVS,只需要輸入 emerge cvs

原始碼 1.1: 安裝 CVS

# emerge cvs

CVSROOT 環境變數

在開始之前,有一些 CVS 的基礎您必須要先知道。首先,為了和 CVS 連接,您必須要先知道一個叫 "CVSROOT" 的路徑。CVSROOT 是一個類似網址的字串,告訴cvs程式遠端的伺服器儲藏庫位置以及連線方式。根據位置在本機或遠端,以及您連線的方式,為了讓生活精彩點,CVSROOT 有許多不同的格式。底下是各種格式的範例以及它的說明。

本機的 CVSROOT

原始碼 1.2: 設定 CVSROOT

CVSROOT=/var/cvsroot

這是一個本機的 CVSROOT 路徑範例,您可能會用像這樣的路徑連到本機上位於 /var/cvsroot 的儲藏庫,或是經由 NFS 掛上 /var/cvsroot 的儲藏庫。

遠端密碼伺服器的 CVSROOT

原始碼 1.3: 設定要認證的 CVSROOT

CVSROOT=:pserver:cvs@foo.bar.com:/var/cvsroot

這是一個連接到 foo.bar.com 上位於 /var/cvsroot 儲藏庫的例子。開頭的 ":pserver:" 告訴程式使用包含在 CVS 內的 CVS 密碼伺服器協定連接。一般而言,公開的 CVS 使用這種協定讓匿名使用者存取。

遠端的 rsh/ssh CVSROOT

原始碼 1.4: RSH/SSH CVSROOT

CVSROOT=drobbins@foo.bar.com:/data/cvs

這是一個使用 RSH 或 SSH 協定連接的例子,在這個範例中,CVS伺服器嘗試用 drobbins 帳號來存取放在 foo.bar.com 上的儲藏庫。如果 CVS_RSH 環境變數設定成 "ssh",cvs客戶端將會以 ssh 來連線,否則就使用 rsh。ssh連線方法在注重安全時相當受歡迎。RSH 或 SSH 也可以讓匿名使用者存取。如果想使用這種方法,您必須在 foo.bar.com 有一個登入帳號。

一些其他的事情

除了 CVSROOT 之外,您必須要知道您要您要下載軟您的模組(程式碼的集合)名稱,就算您以匿名的密碼伺服器方式連接時也是一樣。不像匿名的 FTP,匿名使用者的密碼並沒有一定的格式,所以您必須要從軟體的網站或發展者那得到密碼。一但您知道這些資訊以後,就可以準備開始了。

使用 CVS,第一部份

取得原始碼包括兩階段的過程。首先,先登入密碼伺服器。然後再以 checkout 指令取得原始碼。底下是一個取得最新的 Samba 原始碼範例:

原始碼 1.5: 設定 CVSROOT

# export CVSROOT=:pserver:cvs@pserver.samba.org:/cvsroot

第一行的指令設定 CVSROOT 環境變數。如果您沒有設定的話,您必須要在 cvs 指令後加上 -d:pserver:cvs@pserver.samba.org:/cvsroot,設定 CVSROOT 可以減少需多打字的時間。

使用 CVS,第二部份

接下來是取得最新的原始碼。您或許需要跳到下一部份取得這些指令的說明,然後再回頭看:

原始碼 1.6: 下載原始碼

# cvs login(登入 to cvs@pserver.samba.org)CVS password: (在這裡輸入密碼)# cvs -z5 co sambaU samba/COPYINGU samba/ManifestU samba/READMEU samba/Read-Manifest-NowU samba/RoadmapU samba/WHATSNEW.txt(這只是 cvs co 輸出的片段)

連接 CVS -- 說明

上方的第一行指令登入 CVS,然後第二行告訴cvs客戶端下載 (check out,co) samba模組,並且用 gzip 第五級的壓縮 ("-z5") 來加速下載。任何會在本機建立的新檔案,cvs 標示"U [path]" 表示本機上的檔案已經被更新了。

下載完畢

一旦 checkout 命令完成之後,您會在您目前的目錄下看到包含最新原始碼的 "samba" 目錄。您也會注意到每個目錄底下都有一個名為 "CVS" 的目錄,這個目錄被用來存放一些 CVS 的資料,您可以安全的忽略他。接下來,您並不用擔心是否設定了 CVSROOT 環境變數,因為這些資訊已經被紀錄在 "CVS" 目錄中。記得:您只需要在第一次登入及下載時指定 CVSROOT。

更新原始碼

好了,現在您就有最新的程式碼了!現在您可以去編譯、安裝、觀看原始碼、或是作任何您想作的事情。

有時候,您也許要更新到 CVS 上最新的原始碼。首先,您要先登入到伺服器,您的所有認證資料都存在 "CVS" 目錄中,先進入要下載的目錄中(這個例子中為 samba),接著打:

原始碼 1.7: 更新原始碼

# cvs update -dP

"cvs update" 說明,第一部份

如果有任何新的檔案,cvs 會在那一個項目顯示 "U [path]"。而且,如果您已經編譯過的話,您可能會看到 "? [path]",因為編譯時產生的目的檔 cvs 並不能從遠端找到。

"cvs update" 說明,第二部份

然後注意到我們在命令列加在 "cvs update" 的參數,"-d" 告訴 cvs 建立任何遠端儲藏庫新增的目錄(他預設不這麼作),"-P" 則是移除本機原始碼中任何空的目錄,因為 cvs 頃向保留任何曾經使用過,但是現在不再被使用的目錄。

當您輕鬆的取得最新的原始碼以後,您就完成了。接下來看如何以 CVS 協助開發程式。

2. 以 CVS 協助開發程式

修改檔案

身為一個發展者,您常常會需要修改 CVS 上的檔案。修改時,您只需要修改本機上從儲藏庫下載的檔案。您在檔案上做的改變並不會加到遠端的檔案,直到您告訴 cvs 去"提交 (commit)"修改。當您確認過您的修改沒有問題後,作底下兩個步驟。首先,在原始碼的目錄中輸入下列指令更新原始碼:

原始碼 2.1: 更新原始碼及目錄

# cvs update -dP

CVS 合併其他的改變

如同我們之前所看到的,"cvs update" 將會更新您的原始碼到最新的狀態--但是我作的修改呢?不用擔心,他們並沒有被覆蓋。如果另一位開發者在本機上不存在的檔案作修改,本機上的檔案將會被更新到儲藏庫中的版本。

此外,如果您修改了本機檔案的 1-10 行,而另一位開發者刪除了 40-50 行,在檔案結尾新增 20 行,修改 30-40 行,而且在您之前就提交了他的修改,cvs 會聰明的在本機上的檔案加入這些改變,而且您的所有修改並不會遺失。這讓兩個以上的發展者可以同時修改同一個檔案。

合併並不完美

然而,如果有多個發展者在修改檔案中同一部份,那事情就變得有點複雜。當他發生時,cvs 會告訴您有衝突發生。之前作的改變並不會遺失,但是當 cvs 要求您做一些調整時,您必須要手動作一些修改。

提交

我們將會稍微看一下衝突如何解決,但是現在我們假設在您輸入 "cvs update -dP" 時,並沒有衝突發生。您的程式碼目前已經是最新的,接下來就在目錄中輸入下列的指令來提交您的修改:

原始碼 2.2: 提交修改

# cvs commit

提交時做了什麼?

"cvs commit" 不僅僅是讓儲藏庫中的檔案接受您的修改,cvs 會啟動預設的編輯器讓您輸入一些針對修改的說明。一但您輸入指令,儲存檔案並且離開編輯器,您的改變(包括說明)會被加入遠端的儲藏庫中,並且可以讓團隊中的其他人看到。

檢視紀錄

要看特定檔案(包括所有人作改變時加入的說明)的完整紀錄相當的容易,要查看這些資訊,輸入:

原始碼 2.3: 檢視紀錄

# cvs log myfile.c

"cvs log" 是遞迴的,所以您只要輸入下列的指令就可以看所有檔案的紀錄:

原始碼 2.4: 一頁頁的檢視紀錄

# cvs log | less

提交選項

您或許會想在輸入 "cvs commit" 時使用其他的編輯器。只要設定 EDITOR 環境變數為您要用的編輯器名稱,在您的 ~/.bashrc 中放入下面這一行會是一個好點子:

原始碼 2.5: 設定編輯器

export EDITOR=jpico

除此之外,您也可以在命令列中直接以參數加入說明,如此 cvs 就不用載入任何的編輯器:

原始碼 2.6: 提交時送出小幅度的紀錄

# cvs commit -m 'I fixed a few silly bugs in portage.py'

.cvsrc 檔案

在繼續介紹更多的指令之前,我建議先設定 ~/.cvsrc。在您的家目錄中設定這個檔案之後,可以告訴 cvs 預設的指令參數,而不用去記得每次都要輸入他。底下建議一個 .cvsrc 的設定:

原始碼 2.7: 建議設定

cvs -qdiff -u -b -Bcheckout -Pupdate -d -P

.cvsrc 檔案,續

除了設定一系列 cvs 命令有用的參數,.cvsrc 第一行的指令讓 cvs 進入安靜模式,這會讓 cvs update 輸出比較一致且容易閱讀的文字,而且當您設定了 .cvsrc 之後,可以只打 cvs update 取代 cvs update -dP

在儲藏庫中新增檔案

首先,用您喜歡的編輯器新增檔案,然後輸入下列的文字:

原始碼 2.8: 新增檔案

# cvs add myfile.ccvs server: use 'cvs commit' to add this file permanently

這會告訴 cvs 在下一次執行 cvs commit 時新增這個檔案。在那之前,其他的發展者並不會看到。

在儲藏庫中新增檔案

加入目錄的過程也很類似:

原始碼 2.9: 新增目錄

# mkdir foo# cvs add fooDirectory /var/cvsroot/mycode/foo added to the repository

不像新增檔案,當您加入一個目錄後他會立即在儲藏庫中顯示出來,一旦您將本機的目錄加入 cvs 後,您會發現 "CVS" 目錄會在那個目錄內產生來儲存 cvs 的資料。因此,您可以靠看裡面有沒有 "CVS" 目錄來判斷這個目錄是否加入 CVS 了。

"cvs add" 註解

對了,跟您猜的一樣,在把目錄或當案加入儲藏庫前,您要確定他的上層目錄已經加到 CVS 中。否則,您會得到像這樣的錯誤:

原始碼 2.10: 新增檔案,但傳回了錯誤

# cvs add myfile.ccvs add: cannot open CVS/Entries for reading: No such file or directorycvs [add aborted]: no repository

熟悉 "cvs update",第一部份

在了解如何處理衝突之前,先來了解 "cvs update" 輸出內容。如果您的 ~/.cvsrc 中有 " cvs -q" 您會發現 "cvs update" 的輸出結果很容易閱讀,"cvs update" 靠輸出一個字母,空白,或是檔名來告訴您他作什麼以及觀察到什麼,如同底下的例子:

原始碼 2.11: 更新 CVS

# cvs update -dP? distfiles? packages? profiles

熟悉 "cvs update",第二部份

"cvs update" 用 "?" 告訴您關於那個檔案他並不知道任何事,那並不是在儲藏庫中的檔案,也尚未被安排加到儲藏庫中,底下是所有 CVS 所使用的單一字元的列表:

原始碼 2.12: 訊息: U

U [path]

當有一個檔案在本機上的儲藏庫被建立,或是一個您尚未建立的檔案被更新時使用這個字元。

原始碼 2.13: 訊息: A

A [path]

這個檔案已經被安排要加入並且將會在執行 cvs commit 時被加入。

熟悉 "cvs update",第三部份

原始碼 2.14: 訊息: R

R [path]

這個跟 "A" 差不多,"R" 告訴您這個檔案已經被安排要刪除了,當您執行 cvs commit 時,這個檔案將會從儲藏庫中移除。

原始碼 2.15: 訊息: M

M [path]

這代表這個檔案已經被您修改過。此外,這也可能是儲藏庫中作的改變已經成功的加到這個檔案。

原始碼 2.16: 訊息: C

C [path]

"C" 字元指出這個檔案有衝突,而且您必須要在您作 "cvs commit" 之前手動作一些調整。

衝突解決介紹

現在我們來看看如何解決衝突。我參與 Gentoo Linux 計畫,而我們在 cvs.gentoo.org 設立我們自己的 cvs 伺服器,發展者花了大部份的時間修改 "gentoo-x86" 模組裡面的原始碼。在這個模組裡面,有一個叫做 "ChangeLog" 的檔案(您大概猜到)存放在這個儲藏庫裡面所有檔案的修改說明。

衝突的範例

因為幾乎每位發展者在 CVS 上做修改時都會去修改這個檔案,這是主要的衝突來源。底下是一個衝突的範例,假設我在 ChangeLog 的頂端加入下面幾行:

原始碼 2.17: 更新紀錄

date 25 Feb 2001這是我自己加入的東西

然而,假設在我可以提交之前,另一位發展者在 ChangeLog 的頂端加入下面幾行並且提交了他的修改:

原始碼 2.18: 更新紀錄 2

date 25 Feb 2001這是另一位發展者加入的部份

衝突的範例,續

現在當我執行 cvs update -dP (提交前您應該都做這個動作),cvs 並不能夠把他的修改合併到我的檔案當中,因為我們都加在這的檔案的相同部份 -- cvs 如何判斷使用那一個版本?所以,我得的了底下的錯誤:

原始碼 2.19: CVS 錯誤

RCS file: /var/cvsroot/gentoo-x86/ChangeLog,vretrieving revision 1.362retrieving revision 1.363Merging differences between 1.362 and 1.363 into ChangeLogrcsmerge: warning: conflicts during mergecvs server: conflicts found in ChangeLogC ChangeLog

解決衝突,第一部份

唉--有衝突!幸好這很容易修正。如果我用編輯器打開這個檔案,我在檔案頂端看到下列的文字:

原始碼 2.20: 更新紀錄衝突

<<<<<<< ChangeLogdate 25 Feb 2001這是我自己加入的東西=======date 25 Feb 2001這是另一位發展者加入的部份 >>>>>>> 1.363

解決衝突,第二部份

cvs 不是以一個版本蓋掉另一個版本,而是在 ChangeLog 檔案中加入兩個版本,並且以特殊的分隔符號清楚的標記衝突的地方。現在,由您決定在這部份應該出現的內容,在這個範例中,取代後的文字並不是兩個版本中的一個,而是合併兩者:

原始碼 2.21: 更新紀錄

date 25 Feb 2001這是我自己加入的東西這是另一位發展者加入的部份

現在我已經用上列的文字取代衝突的部份(並且移除了 "=======" 之類的標記),我現在可以毫無問題的提交我的修改。

解決衝突的技巧

當您需要去編輯衝突的檔案時,確認您已經看過整個檔案來找到所有的衝突,如果有衝突您忘了修改,cvs 在您修改前並不允許您提交。移除 cvs 加到檔案中的標記也相當重要。還有另一個技巧,如果您在修正時犯了錯誤並且意外的儲存了,您可以在 ".#filename.version" 檔案中找到原始的備份版本。

移除檔案

現在是學習 CVS 技能最後一項--移除儲藏庫中的檔案。移除檔案是兩階段的過程。首先,刪除在本機上的檔案,然後執行 cvs remove 指令:

原始碼 2.22: 移除檔案

# rm myoldfile.c# cvs remove myoldfile.c

移除檔案,續

這個檔案會被預定在下一次提交時從儲藏庫中刪除。一旦提交之後,檔案將會儲藏庫中移除,但是 cvs 不會把他丟棄,而會保存完整的內容及修改紀錄,以便未來當您需要時可以找到。這是 cvs 保護您的原始碼的其中一個方法。

cvs remove 是遞迴的,這代表您可以刪除一系列的檔案,然後執行 cvs remove 而不需要外加其他的參數。這樣的話會讓所有被刪除的檔案在下次提交時刪除。

移除目錄

如果您想要移除整個目錄,我建議您依照下列的步驟。首先,刪除在這個目錄中的所有檔案:

原始碼 2.23: 移除目錄

# rm *.c# cvs remove

移除目錄,續

然後,執行提交:

原始碼 2.24: 提交改變

# cvs commit

這裡有一個技巧。執行下列的步驟刪除目錄:

原始碼 2.25: 刪除目錄

# cd ..# cvs remove mydir# rm -rf mydir

注意這裡移除目錄並不用執行提交,目錄立即從儲藏庫中移除。

完成!

CVS 的介紹已經完畢了,我希望這份教學很有用。有更多關於 CVS 的資料我可以加到這篇教學中,但是感謝這裡有許多很棒的 CVS 資源讓您可以獲得更多 CVS 的知識:

關於這分文件

這分文件的原始版本是發表在 IBM developerWorks,所有權屬於 Westtech Information Services。這分文件是從他的原始版本修改而來,並且包含許多 Gentoo Linux 文件團隊做的改進。

==============================================

注意:第一次导出以后,就不是通过cvs checkout来同步文件了,而是要进入刚才cvs checkout project_name导出的project_name目录下进行具体文件的版本同步(添加,修改,删除)操作。

将文件同步到最新的版本
cvs update
不制定文件名,cvs将同步所有子目录下的文件,也可以制定某个文件名/目录进行同步
cvs update file_name
最好每天开始工作前或将自己的工作导入到CVS库里前都要做一次,并养成“先同步 后修改”的习惯,和Virvual SourceSafe不同,CVS里没有文件锁定的概念,所有的冲突是在commit之前解决,如果你修改过程中,有其他人修改并commit到了CVS 库中,CVS会通知你文件冲突,并自动将冲突部分用
>>>>>>
content on cvs server
<<<<<<
content in your file
>>>>>>
标记出来,由你确认冲突内容的取舍。
版本冲突一般是在多个人修改一个文件造成的,但这种项目管理上的问题不应该指望由CVS来解决。

确认修改写入到CVS库里
cvs commit -m "write some comments here" file_name

注意:CVS的很多动作都是通过cvs commit进行最后确认并修改的,最好每次只修改一个文件。在确认的前,还需要用户填写修改注释,以帮助其他开发人员了解修改的原因。如果不用写-m "comments"而直接确认`cvs commit file_name` 的话,cvs会自动调用系统缺省的文字编辑器(一般是vi)要求你写入注释。
注释的质量很重要:所以不仅必须要写,而且必须写一些比较有意义的内容:以方便其他开发人员能够很好的理解
不好的注释,很难让其他的开发人员快速的理解:比如: -m "bug fixed" 甚至 -m ""
好的注释,甚至可以用中文: -m "在用户注册过程中加入了Email地址校验"

修改某个版本注释:每次只确认一个文件到CVS库里是一个很好的习惯,但难免有时候忘了指定文件名,把多个文件以同样注释commit到CVS库里了,以下命令可以允许你修改某个文件某个版本的注释:
cvs admin -m 1.3:"write some comments here" file_name

添加文件
创建好新文件后,比如:touch new_file
cvs add new_file
注意:对于图片,Word文档等非纯文本的项目,需要使用cvs add -b选项按2进制文件方式导入,否则有可能出现文件被破坏的情况
比如:
cvs add -b new_file.gif
cvs add -b readme.doc

然后确认修改并注释
cvs ci -m "write some comments here"

删除文件
将某个源文件物理删除后,比如:rm file_name
cvs rm file_name
然后确认修改并注释
cvs ci -m "write some comments here"
以上面前2步合并的方法为:
cvs rm -f file_name
cvs ci -m "why delete file"
注意:很多cvs命令都有缩写形式:commit=>ci; update=>up; checkout=>co/get; remove=>rm;

添加目录
cvs add dir_name

查看修改历史
cvs log file_name
cvs history file_name

查看当前文件不同版本的区别
cvs diff -r1.3 -r1.5 file_name
查看当前文件(可能已经修改了)和库中相应文件的区别
cvs diff file_name
cvs的web界面提供了更方便的定位文件修改和比较版本区别的方法,具体安装设置请看后面的cvsweb使用

正确的通过CVS恢复旧版本的方法:
如果用cvs update -r1.2 file.name
这个命令是给file.name加一个STICK TAG: "1.2" ,虽然你的本意只是想将它恢复到1.2版本
正确的恢复版本的方法是:cvs update -p -r1.2 file_name >file_name
如果不小心已经加成STICK TAG的话:用cvs update -A 解决

移动文件/文件重命名
cvs里没有cvs move或cvs rename,因为这两个操作是可以由先cvs remove old_file_name,然后cvs add new_file_name实现的。

删除/移动目录
最方便的方法是让管理员直接移动,删除CVSROOT里相应目录(因为CVS一个项目下的子目录都是独立的,移动到$CVSROOT目录下都可以作为新的独立项目:好比一颗树,其实砍下任意一枝都能独立存活),对目录进行了修改后,要求其开发人员重新导出项目 cvs checkout project_name 或者用cvs update -dP同步。

项目发布导出不带CVS目录的源文件
做开发的时候你可能注意到了,每个开发目录下,CVS都创建了一个CVS/目录。里面有文件用于记录当前目录和CVS库之间的对应信息。但项目发布的时候你一般不希望把文件目录还带着含有CVS信息的CVS目录吧,这个一次性的导出过程使用cvs export命令,不过export只能针对一个TAG或者日期导出,比如:
cvs export -r release1 project_name
cvs export -D 20021023 project_name
cvs export -D now project_name
评论

相关推荐

Global site tag (gtag.js) - Google Analytics