使用CVS進行版本管理

作者: Per Cederqvist et al

#//////////////////////////////////////////////////////////////////////
# 使用CVS進行版本管理
# 2000-6-30
# CVS 1.10.7
#
#
#
# Per Cederqvist et al 著
# 廖斌 譯
# 感謝黃箐的輸入和排版工作
# copyrigh: GPL
#
#//////////////////////////////////////////////////////////////////////


快捷內容索引
1. 概述.........................................................1
2. 代碼倉庫.....................................................7
3. 使用CVS開始一個項目..........................................29
4. 主幹版本(Revision).........................................33
5. 分支與合併...................................................41
6. Recarsive behavior...........................................49
7. 增加,刪除,更名文件和目錄...................................51
8. 回顧開發歷史.................................................57
9. 放置二進制文件...............................................59
10 多個開發者的同時工作........................................61
11 主幹版本管理.............................................71
12 關鍵字替代................................................73
13 跟蹤第三方代碼...............................................77
14 你的系統如何同CVS交互........................................81
15 特殊文件.....................................................83
16 附錄
1) CVS命令導向..................................................85
2) CVS命令快速參考............................................115
3) 管理文件的參考習冊.........................................127
4) 影響CVS的所有環境變量......................................141
5) CVS各版本之間的兼容性......................................143
6) 遇到的問題.................................................145
7) Credits....................................................153
8) 對CVS和這本手冊的總是處理..................................155

目錄 ...........................................................157



1 概論

這一章爲從未用過CVS的人寫的,也許以前也從未用過任何版本控制工具。

1.1 什麼是CVS?

CVS是個版本控制系統,使用它你可以記錄你原代碼文件的歷史。
例如,當軟件修改時有時會產生問題(*bugs這裏被譯爲問題),並且你可能在做這
次修改後很長時間不會發現這些問題。使用CVS,你可以容易地回顧老的代碼版本去
發現哪一次的修改導致這些問題。有時候這樣會非常有幫助。


你可能會保留你每一次的代碼版本,這可能會浪費你很多的代碼空間。CVS使用一
種聰明的辦法保存你的多個版本在一個文件中。它僅僅保留版本間的不同內容。如果
你是一個項目中的一組成員之一,CVS也能夠幫助你。除非你特別仔細,你很容易覆蓋其
他人的工 作。一些編輯器,例如GNUEmacs,試圖去判定一個文件是否被兩人同時修改。
不幸的是,如果一個人使用其它的編輯器時,這個安全方式將不再有效。CVS使用讓不同
開發者獨立工作的方式解決了這個問題。每一個開發者的工作都在他自己的目錄內,並且
CVS將 在每個開發者的工作完成後進行合併工作。

CVS是由Dick Grune作爲Shell腳本的一個分支而創建的,1986年10月,在它的第6個發行卷
時,它被投遞到新聞組comp.soures.unix。然而現在的CVS衝突算法中沒有任何代碼是從這
些腳本中來的。

在1989年3月,Brian Berlinor設計並編寫了CVS的代碼。Jett.Polk在以後幫助 Brian 完成了CVS
模型的設計和商業版本支持。

你可以通過不同的方式得到CVS,包括在Internet上自由的下載。如果你想下載CVS和其它CVS
文章以得到更多的信息,請看:

http://www.cyxlic.com
http://www.loria.fr/~molli/cvs-index.html.


有一個叫 info-cvs 的郵件列表是有關CVS的內容。訂閱或取消訂閱這個列表請發郵件到

[email protected]

如果你更喜歡Usenet新聞組,CVS的討論組爲

Comp.software.confg.mgmt.

在將來也許會建一個

Comp.software.confg.mgmt.cvs

的新聞組,

但也許這會是Comp.software.confg.mgmt在有太多討論之後的事情吧。

你也許想訂閱bug-cvs的郵件列表,這在附錄H[BUGS]中有更多的信息。訂閱它請發Email到

[email protected].

1.2 CVS不能做的事
(未譯)
2


3 使用CVS開始一個項目
=======================


因爲更改文件名並且把它們移動到另一個目錄中不是經常發生的,因此你在開始一個新項
目時要做的第一件事是考慮你的文件組織。更改文件名或移動文件並非不可能,但增加了
理解上潛在的費解,並且CVS在更改名字的目錄上特別的敏感。請參見7.4節[移動文件]。

(* 譯者注: 在Unix中改名和移動是相同的)。

下一步做的事取決於手中的情況。

3.1 建立文件

第一步是在倉庫中建立文件。這可以使用多種不同的方法來完成。

--------------------------------------------------------------------

3.1.1 建立一個目錄樹

當你開始使用CVS時,你可能已經有幾個項目可以使用CVS進行管理了。在這種情況下,
最容易的方法就是使用: "import"命令。一個例子是最容易解釋如何使用它的。假定你現
在有一些你想放到CVS中的文件在"wdir"中,並且你想讓它們放在數據倉庫中的如下目錄:

" $CVSROOT/yoyodyne/rdir"

你可以使用如下命令:

 $cd wdir
 $cvs inport -m "Inported Sources" yoyodyne/rdir yoyo start

如果你沒有使用"-m"參數記錄一個日誌信息,CVS將調用一個編輯器(*譯者注:通常是vi)
並且提示輸入信息。"yoyo"字符串是開發者標箋,"start"是發行標箋。他們沒有什麼特別
的意義,僅僅是因爲CVS的需要才放在這裏。

請參見第13章[跟蹤代碼],得到更多的這方面信息。

你現在可以檢查一下它是否有效了,然後可以刪除你原來的代碼目錄。

 $cd
 $mv dir dir.orig
 $cvs checkout yoyodyne/dir
 $diff -r dir.orig yoyodyne/dir
 $rm -r dir.orig.

爲了避免偶然進入到你原來的目錄中去編輯文件,刪除原來的代碼是個好主意。當然,在
你刪除之前保留一份備份到其它地方也是明智之舉。

"checkout"命令能使用模塊名作爲參數(正如前面所有例子)或是一個相對於 $CVSROOT的路
徑,如同上面的例子。你應當檢查CVS目錄中的權限情況是否合適,應當使它們屬於某一個
特定的組。請參見2.2.2.節[文件權限]。

如果你想"import"的一些文件是二進制代碼,你可以使用一些特殊的方法表明這些文件是否
是二進制文件。請參見C.2節[Wrappers]。


------------------------------------------------------------------------------------

3.1.2 從其它版本控制系統建立文件

如果你有一個其它版本控制系統維護的項目,例如RCS,你也許希望把這些文件放到CVS中,
並且要保留這些文件的歷史。以下是一些討論。

從RCS:
如果你使用RCS,找到RCS文件??通常一個文件名叫"foo.c"的文件會有"RCS/foo.c,v"的RCS文
件。(但它有可能在其它地方,請看RCS的文檔以得到相關信息)。如果文件目錄在CVS中不存
在,那在CVS中創建它。然後把這些文件拷貝到CVS的倉庫目錄中(在倉庫中的名字必須是帶
",v"的原文件;這些文件直接放在CVS中的這個目錄下,而非"RCS"子目錄中)。這是在CVS中
一個爲數不多的直接進入CVS倉庫直接操作的情況,而沒使用CVS命令。然後你就可以把它們
在新的目錄下"checkout"了。

當你把RCS文件移動CVS中時,RCS文件應在未被鎖定的狀態,否則移動操作時CVS 將會出
現一些問題。

從其它版本控制工具

許多版本控制工具都可以輸出"RCS"格式的標準文檔。如果你的版本控制工具可以做到這一
點,直接輸出RCS文件,然後按照上面的例子做就可以了。

如果你的版本工具不能輸出RCS文件,那麼你必需要寫一個腳本文件來,每次取出一個版本
然後把它放到CVS中去。下面提到的"sccsarcs"腳本就是一個很好的例子。

從SCCS:

有一個"sccsarcs"的腳本文件可以做把SCCS的文件轉化成RCS文件,這個文件放在CVS原代碼
目錄的"contrib"目錄中。注意:

你必須在一臺同時安裝了RCS和SCCS的機器上運行它。並且,正如其它在"contrib."目錄中的
其它腳本一樣。(你的方法也許是變化多端的)

(*譯者注:我並未查看過CVS的contrib目錄:-(,因此不知道這下面都有些什麼)。

從PVCS:

在"contrb"中有一個叫"pves-to-rcs"的腳本可以轉換PVCS到RCS文件。你必須在一臺同時有
PVCS和RCS的機器上運行它。

請看腳本中的註釋以得到更多細節。

3.1.3從無到有建立一個目錄樹

建立一個新的項目,最容易的方法是建立一個空的目錄樹,如下所示:

 $mkdir tc
 $mkdir tc/man
 $mkdir tc/testing

在這之後,你可以"import"這個(空)目錄到倉庫中去。

 $cd tc
 $cvs import -m "created directory structure"yoyodyne/dir yoyo
start

然後,當新增一個文件時,增加文件(或目錄)到倉庫中。請檢查 $CVSROOT中的權限是否正確。

-------------------------------------------------------------------------------------------

3.2 定義模塊

下一步是在"moduyes"文件中定義模塊。這不是嚴格需要的,但模塊能把相關的目錄和文件容易
關聯起來。下面的例子可以充分演示如何定義模塊。

1. 得到模塊文件的工作拷貝。

 $cvs checkout CVSROOT/modules
 $cd CVSROOT

2.
編輯這個文件並寫入定義模塊的行。請參見2.4節[管理文件的介紹]。有一個簡單介紹,參見C.1節
[模塊文件]。有它的詳細描述。你可以使用下面的行定義模塊"tc":

tc yoyodyne/tc

3. 提交你的更改到倉庫

 $cvs commit -m "Added tc module." modules

4. 發行模塊文件

 $cd
 $cvs release -d CVSROOT

4
=======


5 分支與合併
==================
CVS允許你獨立出一個派生的代碼到一個分離的開發版本---分支。當你改變一個分支中的文
件時,這些更改不會出現在主開發版本和其它分支版本中。

在這之後你可以使用合併(merging)把這些變更從一個分支移動到另一個分支(或主開發版
本)。合併涉及到使用“cvs update -j”命令,合併這些變更到一個工作目錄。你可以確認
(commit)這次版本,並且因此影響到拷貝這些變更到其它的分支。

-----------------------------------------------------------------------------------

5.1 何時應當創建一個分支

假定tc.c發行版已完成。你正在繼續開發tc.c,計劃在2個月後發行1.1的版本。在不久以後你的
客戶開始抱怨說代碼有些問題,你檢查了一下1.0的發行版(請參見4.4節[標箋])並且找到了這
個錯誤(這將會有一個小小的更正)。但是,這個當前的版本是處於一個不穩的狀態,並且在下
一個月纔能有希望穩定下來。這樣就沒有辦法去發行一個最新的現有版本去更正問題。

這時就可以去創建基於這棵版本樹1.0版的分支。你可以修改這棵樹的分支而不影響到主幹。當
修訂完成時,你可以選定是否要把它同主幹合併或繼續保留在這個分支裏。

-----------------------------------------------------------------------------------

5.2 建立一個分支

你可以使用“tag -b”去建立一個分支。例如,假定你在工作於一個工作拷貝中:

 $cvs tag -b rel_1_0_patches

這將基於當前的拷貝分離出一個分支,並分配“rel_1_0_patches”的名字。

懂得分支是在CVS倉庫中創建,而非在工作拷貝中創建的是非常重要的。正上面的例
子,創建一個基於當前版本的分支不會自動把當前的工作拷貝轉到新的分支上。欲知
詳情,請看5.3節[進入 一個分支]。你也可以不參考任何工作拷貝而建立一個分支。
你可以使用rtag命令:

cvs rtag -b -r rel-1-0 rel-1-0-patches tc.

“-r rel-1-0”說明這個分支是基於標誌了rel-1-0的版本文件,它不是從最新的版本
開始分支.這對需要從老的版本進行分支很有用(例如:當修訂一個過去的穩定版本時)

當使用“tag”標誌,這個“-b”標誌告訴rtag去創建一個分支(而非是這個版本的符號
連接)。注意標記“rel-1-0”可能對不同的文件有不同的版本數字。因此,這個命令的結果
是爲tc模塊建立了一個命名爲“rel-1-0-patches”的新版本分支,它是基於標記爲“rel-1-0”
的版本樹。

-----------------------------------------------------------------------------------

5.3 進入分支

你可以通過兩種方式進入分支:重新checkout或是從現存的拷貝進入。重新checkout使用
checkout命令並帶上“-r”標識,後面是這個分支的標箋(tag)名。(請看5.2[創建一個分支]):

 $cvs checkout -r rel-1-0-patches tc.

或者如果你已有了一個拷貝,你可以使用“update -r”命令轉到這個分支。

 $cvs update -r rel-1-0-patches tc.

或者使用另一個等同的命令:

 $cd tc
 $cvs update -r rel-1-0-patches

這對現有拷貝爲主幹代碼或是其它分支都是有效的.上面的命令將把它轉到命
名的分支。同“update”命令相類似。“update -r”合併你所做的任何改變,請注
意是否有衝突出現。

一但你的工作拷貝已經轉向一個特定的分支。它將一直保持在這個分支內,除非你
又做了其它的操作。這意味着從這個工作拷貝checkin的變更將加到這個分支的新版
本中,而不影響到主幹版本和其它分支代碼。

想看一個工作拷貝是基於哪一個分支,可以使用“status”命令。在它們輸出中查找
一個“sticky tag”的域(請參見4.9節["sticky tag"],第38頁).那就是你的當前分支號。

 $cvs status -v driver.c backend.c

====================================================================
File: driver.c Status: Up-to-date

Version: 1.7 Sat Dec S 18:25:54 1992
RCS version: 1.7 /u/cvsroot/yoyodyne/tc/driver.c,v
Sticky Tag: rel-1-0-patches (branch: 1.7.2)
Sticky Date: (none)
Stick Option: (none)

Existing Tag:
rel-1-0-patches (branck: 1.7.2)
rel-1-0 (revision: 1.7)


====================================================================
File: backend.c status: Up-to-date

Version: 1.4 Tue Dec 1 14:39:01
Rcs Version: 1.4 /u/cvsroot/yoyodyne/tc/
Sticky Tag: rel-1-0patches(branch:1.4.2)
Sticky Date: (none)
Sticky Option: (none)

Existing Tag:
Rel-1-0-patches (branch: 1.4.2)
Rel-1-0 (revision: 1.4)
Rel-0-4 (revision: 1.4)


請不要因爲每個文件的分支是不同(“1.7.2”和1.4.2")而迷惑。分支的標箋(tag)
是相同的:"rel-1-0-patches",這些相同標箋的文件是相同分支的。在以上的例子中,分支建
立之前,"driver.c" 比 "backend.c"有更多的變更,因此它們的版本編號是不同的。請參見5.4節
[分支和主幹版本號]去了解分支如何構建原理的細節。

--------------------------------------------------------------------------------------

5.4 分支與主幹版本

通常,一個文件的主幹版本歷史是一個增長線(請看4.1[主幹版本]頁):

+-----+ +-----+ +-----+ +-----+ +-----+
! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !----! 1.5 !
+-----+ +-----+ +-----+ +-----+ +-----+

然而,CVS並不侷限於線性的開發。主幹版本可以分爲不同的分支,每一個分支可
以是一個獨立的自我維護的開發線。而在一個分支中的變更可以很容易的轉移到主幹中。
每一個分支均有一個分支號,由一個“.”分離的十進制奇數組成,分支號的編排依
賴於它分離出的主線版本。使用分支號允許從一個特定版本分離出多個分支。

所有的分支版本都依賴於它的原始分離版本號。下面的例子將展示這一點。


+-------------+

1.2.2.3.2 分支 -> +--! 1.2.2.3.2.1 !

! +-------------+

!
+---------+ +---------+ +---------+
1.2.2 分支-> +--! 1.2.2.1 !----! 1.2.2.2 !----! 1.2.2.2 !
! +---------+ +---------+ +---------+
!
!
+-----+ +-----+ +-----+ +-----+ +-----+
! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !----! 1.5 ! <- 主幹
+-----+ +-----+ +-----+ +-----+ +-----+
!
!
! +---------+ +---------+ +---------+
1.2.4 分支-> +--! 1.2.4.1 !----! 1.2.4.2 !----! 1.2.4.2 !
+---------+ +---------+ +---------+



你是如何創建具體的分支號的細節通常不是你需要考慮的,但這裏談談它如何工作。

當CVS建立一個分支號時,它先得到第一個未用的偶數,開始的數字是2,例如你
從6.4的主幹版本創建分支時,分支號爲6.4.2所有分支號碼末位爲0的號碼用於CVS內
部,(例如6.4.0)。(請參見5.5節[內部分支號]44頁)分支1.1.1有特別的含義,請看13章
[跟蹤代碼]。

-----------------------------------------------------------------------------------

5.5 內部分支號碼

這一節描述CVS的內部分支(magic branches) (* 譯者注:magic branch 譯爲內部分支)
特性。在大多數情況下,你不用考慮內部分支號碼,CVS將爲你進行管理。然而,在
一些特定條件下,它將顯現出來,因此理解它如何工作將是有用的。一般的,分支號
碼將由奇數個 "."分隔的十進制整數組成。請看4.1節[版本號碼]。然而那並非完全是這
樣的,由於效率的原因,CVS有時插入一個額外的“0”在右末的第二個位置(1.2.4
變爲1.2.0.4,8.9.10.11.12變爲8.9.10.11.0.12等)。

CVS將會很好的將這些變換隱蔽在背後進行,但在一些地方,這種隱蔽並不完全:

* 內部分支編號會出現在CVS的日誌(log)文件中。
* 你不能夠對 "cvs admin" 使用符號分支名。


你可以使用admin命令去爲一個分支重新分配一個RCS希望的那樣的符號名。如果
R4patches是一個分配給分支1.4.2(內部分支編號爲1.4.0.2)的一個文件"numbers.c"的
命名,你可以使用如下命令:

 $cvs admin -NR4patches:1.4.2 numbers.c

它將只在至少一個版本已經提交到這個分支時纔會有效。請非常小心不要把一個標
箋(tag)分配給了一個錯誤標識號(現在沒有看到昨天的一個標箋是如何分配的)。

----------------------------------------------------------------------------------

5.6 合併一個整個分支

你可以合併一個分支到你的工作目錄在“update”命令中“-j 分支號”的標識。使
用“-j 分支號”將合併這個派生分支點與原版本的最新版之間的變更到你的工作目錄
“-j”的意思是“join”。

我們現在來考察下面這棵樹:


+-----+ +-----+ +-----+ +-----+
! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 ! <- 主幹
+-----+ +-----+ +-----+ +-----+
!
!
! +---------+ +---------+
R1fix 分支-> +--! 1.2.2.1 !----! 1.2.2.2 !
+---------+ +---------+


分支1.2.2分配了一個Rifix的名字.下面的例子假定模塊"mod"只包含一個文件"m.c"

 $cvs checkout mod # 得到最新的1.4版
 $cvs update -j R1fix m.c # 合併所有在分支中的改變,即:1.2與1.2.2.2
# 之間的變化到這個文件的工作目
錄.

 $cvs commit -m "Included R1fix # 建立1.5版


在合併時可能會發生衝突,如果這種情況發生,你可以在提交新版本之前解決它。請
參見10.3節[衝突的例子]。

如果你的原文件中包含關鍵字(請看第12章[關鍵字替代])。你可能會得到比嚴格意義
上的衝突更多的衝突信息。請參見5.10節[合併和關鍵字],去了解如何避免這個問題。
"checkout"命令也支持使用"-j"參數。下面的例子同上面所用的例子有相的效果。

 $cvs checkout -j R1fix mod.
 $cvs commit -m "Included R1fix"

---------------------------------------------------------------------------------

5.7 從一個分支多次合併。


繼續我們上面的例子。現在這棵樹看起來是這樣的:

+-----+ +-----+ +-----+ +-----+ +-----+
! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !----! 1.5 ! <- 主幹
+-----+ +-----+ +-----+ +-----+ +-----+
! *
! *
! +---------+ +---------+
R1fix 分支-> +--! 1.2.2.1 !----! 1.2.2.2 !
+---------+ +---------+


正如上面所討論的,分支1.2.2.2所引導的“*”號表示從Rifix分支到主幹的合併。

現在我們繼續開發Rifix分支:

+-----+ +-----+ +-----+ +-----+ +-----+
! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !----! 1.5 ! <- 主幹
+-----+ +-----+ +-----+ +-----+ +-----+
! *
! *
! +---------+ +---------+ +---------+
R1fix 分支-> +--! 1.2.2.1 !----! 1.2.2.2 !----! 1.2.2.3 !
+---------+ +---------+ +---------+

然後你可能會希望合併新的變更到主幹中去。如果你仍使用“cvs update -j Fifix m.c"
cvs將試圖合併你已經合併過的東西,這可能寫導致一些不希望發生的東西。


因此,你必須表達清楚你希望只合並未被合併的內容的意思。這樣需要使用兩個
“-j“參數。CVS合併從第一個“-j”的版本到第二個“-j”版本的變化。例如,在我們上面

的例子中:

cvs update -j 1.2.2.2 -j R1fix m.c

如果出現的問題是你需要手工指定1.2.2.2的版本號,一個更好的方法是使用:

cvs update -j R1fix:yesterday -j R1fix m.c

然而,更好的方式是在每一次合併後重新放一個標箋給Rifix分支,然後使用標
箋做後的合併:

cvs update -j merged_from_Rifix_to_trunk -j R1fix m.c

----------------------------------------------------------------------------------

5.8 合併兩個任意版本之間的不同

使用兩個“-j”標誌,這個update(和checkout)命令能合併兩個任意不同的版本
到你的工作目錄。

 $cvs update -j 1.3 backend.c

將把1.5版本恢復到1.3版本,所以一定要注意版本的順序。

如果你在操作多個文件時使用這個選擇項,你必須瞭解在不同的文件之間,版本的
數字可能是完全不同的。你必須使用標箋(tag)而不是使用版本號來完成多個文件
的操作。使用兩個“-j”操作也能會恢復增加或刪除的文件。例如,假定你有一個
叫“file1”的文件在在於1.1版本中,然後你在1.2版本中刪除了它,下面是如何操作的例子:

 $cvs update -j 1.2 -j 1.1 file1
file1
 $cvs commit -m test
checking in file1;
/tmp/cvs-sanity/cvsroot/first-dir/file1 file1,v
new revision:1.3; previous revision:1.2 done
 $

------------------------------------------------------------------------------------

5.9 合併能添加和刪除文件

如果你在合併時的改變涉及到添加或刪除一些文件,“update -j”將反映這些變化。
例如:

cvs update -A
touch a b c
cvs add a b c ; cvs ci -m "added" a b c
cvs tag -b branchtag
cvs update -r branchtag
touch d ; cvs add d
rm a ; cvs rm a
cvs ci -m "added d , removed a"
cvs update -A
cvs update -j branchtag


在這些命令之後(注意要commit),文件a將被刪除,而文件d將被加入到主幹。

-------------------------------------------------------------------------------------

5.10 合併和關鍵詞


如果你合併的文件包含關鍵詞(參見第12章[關鍵詞替代],73頁),你通常將會在
合併時得到 無數個衝突報告,因爲在不同版本中非常不同。

因此,你常需要在合併時使用“-kk”(參見12.4節[替代模式],75頁)選擇項。使用
關鍵字名字,而非去擴展關鍵字的值的方法,這個功能選擇項確保你合併的版本之間互相相
同,而避免了衝突。

例如:假設你有一個文件如下:

+---------+
br1 -> +--! 1.1.2.1 !
! +---------+
!
!
+-----+ +-----+
! 1.1 !----! 1.2 !
+-----+ +-----+



並且你的當前工作目錄拷貝爲主幹(1.2版本)。那麼對於以下的合併將會產生一個
衝突的結果。請看例子:

 $cat file1
Key  $Revision: 1.3  $
...
 $cvs update -j br1
U file1
RCS file: /cvsroot/first-dir/file1,v
retrieving revision 1.1
retrieving revision 1.1.2.1
Meging differences between 1.1 and 1.1.2.1 into file1
rscmerge: warning: conflicts during merge
 $ cat file1
 $<<<<<<< file1
Key  $Revision: 1.3  $
=======
Key  $Rerision: 1.1.2.1  $
 $>>>>>>> 1.1.2.1
...


衝突發生在試圖將1.1和1.1.2.1合併到你的工作目錄中去的時候。因此,當這個
關鍵詞從“Revision:1.1"到"Revision:1.1.2.1"時,CVS將試圖合併這個變化到
你工作目錄, 這就同你的目錄中的變更“Revision:1.2"發生了衝突。

以下是使用了:“-kk”後的例子:

 $cat file1
key  $Revision: 1.3  $
...
 $cvs update -kk -j br1
V file1
RCS file: /cvsroot/first-dir/file1,v
retrieving revision 1.1
retrieving revision 1.1.2.1
Merging differences between 1.1 and 1.1.2.1 into file1
 $ cat file1
key  $Revision: 1.3  $
...

在這裏版本“1.1”和“1.1.2.1"都擴展爲單純的 "Revision",因此,合併時就不會
發生衝突了。

然而,使用 "-kk" 參數還一個主要的問題。即,它使用了CVS通常使用的關
鍵字擴展模式。在特殊情況下,如果模式使用針對二進制文件的 "-kb"
參數。這將會產生問題。因此,如果你的數據庫中包括有二進制文件,你將
必須手工處理這些問題,而不能使用 "-kk"。

10 多個開發者同時工作
---------------------

當多個開發者同時參與一個項目時,常常會發生衝突。一般經常發生的情況是兩個人想
同時編輯一個文件的時候。它的解決方法之一是文件鎖定或是使用保留式的checkout,這種
方法允許一個文件一次只允許一個人編輯。這是一些版本控制系統的唯一解決方式,包括
RCS和SCCS。現在在CVS通常使用保留式checkout的方法是使用"CVS admin-1"命令(參見A-6-1AB
[admin選擇項])。在下面將解釋這不是一種好的智能的解決方式,當它是許多人喜歡使用的
一種方式。下面也將講述可以使用適當的方法來避免兩個人同時編輯一個文件,而非使用軟件
的方式強迫達到這一點。

在CVS中默認的方法是"unreserved checkout"--非保留式的導出。在這種方法下,開發者
可以同時在他們的工作拷貝中編輯一個文件。第一個提交工作的沒有一種自動的方法可以知道
另一個人在編輯文件。另一個人可能會在試圖提交時得到一個錯誤信息。他們必須使用CVS命令
使他們的工作拷貝同倉庫的內容保持更新。這個操作是自動的。

CVS可以支持facilitate多種不同的通信機制,而不會強迫去遵守某種規則,如"resered
checkouts"那樣。以下的部分描述這些不同的方式是如何工作的,和選擇多種方式之間涉及到
的一些問題。

10.1 文件狀態

基於你對導出的文件使用過的操作,和這些文件在倉庫中的版本使用過的操作,我們可以
把一個文件分爲幾個狀態。這個狀態可以由"status"命令得到,它們是:

up-to-date:
對於正在使用的這個分支,文件同倉庫中的最後版本保持一致。

Locally Modified:
你修改過文件,但沒有"commit"。

Locally added:
使用了"add"命令增加文件,但沒有"commit"

Locally Removed:
你使用了"remove"命令,但沒有"commit"

Needs checkout:

其他人提交了一個更新的版本。這個狀態的名字有些誤導,你應當使用"update"而非

"checkout"來更新新的版本。

Needs Patch:
象"Needs checkout"一樣,但CVS服務將只給出Patch(補丁)文件,而非整個文件。而
給出Patch和給出整個文件的效果是相同的。

Needs Merge:
一些人提交了一個更新版本,而你卻修改過這些文件。

File had conflicts on merge:

這同"Locally Modified"相象,只是"update"命令給出了一個衝突信息。如果你還沒有
解決衝突,那麼你需要解這個問題,解決衝突的方法參見10.3節[衝突的例子].

Unkown:

CVS不知道關於這個文件的情況.例如,你創建了一個新文件,而沒有使用"add"命令

爲了幫助弄清楚文件的狀態,"status"也報告工作版本(working
vevision),這是這個文件是從哪個版本來的,另外還報告"倉庫版本"(Repository
vevision)。這是這個文件在倉庫中的這個版本分支的最後版本。

"status"命令的選擇項例在附錄B[invoking cvs]。有關"sticky tag"和"sticky
date"輸出內容的信息,參見4.9節[sticky tags]。有關"sticky options"輸出內容參見"-k"選擇項,
A.16.1節[update選擇項]。

你應當把"update"和"status"命令放在一起來認識。你使用"update"使你的文件更新到最
新狀態,你使用"status"命令來得到"update"命令將會做何種操作。(當然,倉庫中的狀態將可
能會在你運行update之前變化)。事實上,如果你想使用一個命令得到比使用"status"正式的狀
態信息,你可以使用:

 $cvs -n -q -update

這裏"-n"選擇項表示不真正執行update,而只顯示狀態;"-q"選擇項表示不打印每個目錄的
名字。有關更多的關於"update"命令的住處參見附錄B[使用CVS]。

10.2 使一個文件更新到最版本

當你想更新或是合併一個,使用update命令。對於一個不是最新版本的文件,這個命令大略等
同於"checkout"命令:最新版本從倉庫中提出並放到工作目錄中。

當你使用"update"命令時,你修改過的文件在任何情況下不會受到損害。如果在倉庫中沒有更
新的版本,"update"時你的代碼沒有任何影響。當你編輯過一個文件,並且倉庫中有更新版本,那
麼"update"將合併所有的變更到你的工作目錄。

例如,想象一個你導出了一個1.4版的文件並且開始編輯它,在某一時候其他人提交了1.5版,然
後又提交了1.6版,如果你運行update命令,CVS將把1.4版到1.6版之間的變更放到你的文件中。
如果在1.4版和1.6版之間的改變太靠近於的你一些變更的話,那麼一個"覆蓋"("overlop")衝突
就發生了。在這種情況下將輸出一個警告信息,然後結果保留的文件中包含了有衝突代碼的兩個版
本,由特別的符號所分隔開。請參見A.16節[更新],可以得到關於"update"命令的一個完全的描述。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章