Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
CVS入門
[go: Go Back, main page]

以下は、小金丸信幸が著作し BSD Magazine No.3 に掲載した原稿です。 BSD Magazine 編集部の許可を得てここに転載します。
[修正:平成16年(2004年)01月12日 (月)]改版履歴

CVS入門

小金丸 信幸/Nobuyuki Koganemaru
kogane@koganemaru.co.jp


はじめに
リビジョン番号について
使用例
(1)管理ディレクトリの作成と環境変数の設定
(2)cvs init の実行
(2)初期登録(インポート)
(4)チェックアウト
(5)コミット
(6)ファイルの追加
(7)リビジョン番号 1.1 から始めるための登録
(9)タグの設定
(10)ブランチの指定
(11)ソースファイルの差分を見る
(12)競合したファイルの修正
(13)マージ
(14)変更履歴を見る
(15)誰がチェックアウトしているかを見る
(16)コミットの履歴を調べる
(17)status コマンド
(18)cvs コマンドの形式を忘れたとき
その他の事項
(1)置換されるキーワード
コマンド形式
ネットワークでの cvs 使用法
server モードの設定方法
(1)サーバー側の設定
(2)クライアント側での cvs 環境の設定
(3)クライアントでの実行
(4)Secure shell (ssh)「安全シェル」を使った server モード
pserver モードの設定方法
(1)サーバー側の設定
(2)クライアントでの cvs 環境の設定
(3)クライアントでの実行
kserver モードの設定方法
その他
FreeBSD 固有の拡張
tcsh での cvs コマンドの利用
コミットしたらメールを送る
他で作成された cvs ファイルを取り込むには
古いリビジョン番号のソースを取り出したい
修正を取り消したい
バイナリファイル
patch ファイルを作成する
Windows での cvs の使用
Windows での cvs コンパイル

はじめに

プログラムを開発する上で、バージョン管理は大切な仕事である。 長い間メンテナンスを行っているシステムの場合、 すでにリリースした古いバージョンのプログラムと現在機能追加などを行っているバージョンのソースプログラムを管理していくのはたいへんなことである。 しかも、リリースが何回も行われている場合は、各バージョンのソースを保存したり、 あるバージョンと現在のバージョンの違いなどを検査するのにバージョン番号が合っているかどうかの確認を注意深く行うことが要求される。 古いバージョンを新しいバージョンで置き換えられない場合は、古いバージョンを元にした改造を行うことになる。 そして、そのバージョンの管理も追加して行わなければならないなど、 わずらわしい管理作業が増えることになる。

コンピュータで行うバージョン管理システムを使えば、 これらの管理のほとんどを解決することができる。

一方、プログラム開発では、新規開発中に頻繁にソースファイルを修正する。 ちょっとした修正でバグが発生し、 以前のソースはどうだったなどといって前のソースを見ることになる。 そんなとき、バージョン管理を行っていれば便利である。もちろん、 開発中はある区切りのいいタイミングで登録 (後で述べるがコミットと言う)を行っておく必要がある。 プログラムができあがった時点で、再び新しいバージョン番号 (たとえば 1.1) として新規登録を行うと良いだろう。

有名なバージョン管理システムには、SCCS と RCS がある。 SCCS は米国ベル研究所で UNIX 上のシステムとして開発され、 後に UNIX の一部として取り入れられている。 UNIX のライセンスがあるワークステーションには添付されているが、 フリーの UNIX もどきのシステムや Windows などでは使用できない。 一方、RCS はバークレー版の UNIX にコントリビュートされ、自由に使用することができる。 一部は MS-DOS などでも使用できるようである。

現在、CSSC という SCCS と同じ機能を目指したフリーの SCCS が開発されつつある。 しかし、まだ、すべての機能を満足するまでには到っていない。

これから説明する CVS(コンカレントバージョンシステム) は、 RCS システムを利用したバージョン管理システムである。RCS では、 個々のファイルのバージョン管理はできるが、 ファイルツリー全体を管理するのは繁雑で難しいものであった。 CVS では、この欠点を改良し、ファイルツリー全体を簡単に管理できるようにしている。 CVS にはリリース等を管理するタグが導入され、リリース全体のファイルを識別できるようになっている。 すなわち、リリースタグを REL_2_1 としたとき、A ファイルのバージョンは 1.2、 B ファイルのバージョンは 1.4、C ファイルのバージョンは 1.3 となっている時点で、 それらのファイル全体を REL_2_1 というタグで識別できるようになっている。

SCCS や RCS はファイルを変更するとき、他の人が同じファイルを修正しないよう にファイルをロックする。最初にファイルをロックした人の修正が終わらない限り、 他の人はそのファイルの修正ができないようになっている。しかし、CVS では同時 に複数の人間が同じファイルを変更できるようにしている。このように複数の人間 から同時に 1 つのファイルに修正が施された場合、CVS はできるかぎり自動的に これらの修正をファイルに反映するようにしている。しかし、どうしてもうまくい かない場合には、人間が手動で修正することになる。

CVS は、最初 RCS を内部で呼び出す UNIX のシェル手続きとして作成された。 その後機能が強化され、C で書き直された。 C で作成された CVS も内部で RCS コマンドを呼び出しており、 RCS もまたユニファイド diff(-u オプション) 形式が使える diff コマンドを呼び出していた。 しかし、最近の CVS は RCS および diff コマンドを内部に取り入れているので、 RCS を呼び出すことはない。現在、CVS は UNIX システムはもちろんのこと、 Windows 95/98、Windows NT/2000 などのシステムでも使えるようになっている。 UNIX 側に CVS のサーバーをおけば、Windows(Windows 95、98、NT、2000 は以降 Windows という名称で総称する) 側から呼び出して使用することもできる。すなわち、CVS の管理ファイルは UNIX で保管し、使用するときは Windows に取り出して使用するということである。 このような使い方をする場合でも、変更が必要なのは環境変数だけであり、 Windows 側でファイルを管理するのとまったく同じ方法で使用することができる。

リビジョン番号について

各ファイルには、1.1、1.2、2.3 などのリビジョン番号がつけられる。1.3.2.1、 1.3.2.1.2.1 というリビジョン番号もある。リビジョンは、1.1、1.2、1.3 と増え ていくが、途中で枝分かれするリビジョンも利用できる。ブランチ (枝) には、ブ ランチ番号がつけられ、ピリオドで分けられた奇数個の数字となる。ブランチにあ るリビジョンは、ブランチ番号にピリオドと番号をつけて表す。枝分かれ (ブラ ンチ)はいくつあってもかまわない。図1 にリビジョンツリーの例を示す。1.2.2、 1.3.2、1.3.2.1.2 がブランチ番号であり、ピリオドで分けられた偶数個の番号が すべてリビジョン番号である。

                          ┌────┐
                          │        │
                          │ 1.1    │
  ブランチ                └─┬──┘
    1.2.2                     │
      ↓                      │
                          ┌─┴──┐
      ┌─────────┤        │
      │                  │ 1.2    │
      │                  └─┬──┘     ブランチ
  ┌─┴──┐                │            1.3.2
  │        │                │              ↓             ブランチ
  │ 1.2.2.1│            ┌─┴──┐                       1.3.2.1.2
  └─┬──┘            │        ├─────┐              ↓
      │                  │ 1.3    │    ┌──┴─┐
      │                  └─┬──┘    │        ├────┐
      │                      │          │ 1.3.2.1│        │
      │                      │          └─┬──┘        │
      │                      │              │              │
      │                      │              │              │
  ┌─┴──┐            ┌─┴──┐    ┌─┴──┐    ┌─┴────┐
  │        │            │        │    │        │    │            │
  │ 1.2.2.2│            │ 2.1    │    │ 1.3.2.2│    │ 1.3.2.1.2.1│
  └────┘            └────┘    └────┘    └──────┘

                 図1 cvs(RCS)のリビジョンツリー(木)

なお、SCCS ではリビジョン番号はピリオドで分けられた 2 つの数字であり、同様 に 2 つの数字で表されるブランチ番号とのペアとして管理される (例:1.2 はリ ビジョン番号、1.2.1.3 は 1.2 がリビジョン番号、1.3 がブランチ番号)。

RCS、cvs では、リビジョン番号 / ブランチ番号の使い方が異なっているので注意 すること。

使用例

それでは、てっとり早く理解するために、少し CVS を動かしてみよう。

(1)管理ディレクトリの作成と環境変数の設定

まず、CVS 用の管理ディレクトリを作る。そして、そのディレクトリを環境変数 CVSROOT に設定する。

csh ベースのシェルの場合なら、

% mkdir cvsroot
% setenv CVSROOT `pwd`/cvsroot

カレントディレクトリがホームディレクトリなら .chsrc に

setenv CVSROOT ~/cvsroot

と設定する。

CVSROOT は、接続経路を指定する部分があり、ネットワークを介して CVS を使用 する場合に意味がある。ローカルなファイルの場合は

setenv CVSROOT :local:$HOME/cvsroot

とするが、:local: を省略してもローカルとして扱われるので、

setenv CVSROOT ~/cvsroot

で十分である。

(2)cvs init の実行

管理ディレクトリと環境変数の設定が終わったなら、

% cvs init

を実行する。すると、~/cvsroot/CVSROOT というディレクトリが作成され、 図2のようなファイルが作成される。

% ls ~/cvsroot/CVSROOT
.#checkoutlist  .#notify        commitinfo,v    history         rcsinfo
.#commitinfo    .#rcsinfo       config          loginfo         rcsinfo,v
.#config        .#taginfo       config,v        loginfo,v       taginfo
.#cvswrappers   .#verifymsg     cvswrappers     modules         taginfo,v
.#editinfo      checkoutlist    cvswrappers,v   modules,v       verifymsg
.#loginfo       checkoutlist,v  editinfo        notify          verifymsg,v
.#modules       commitinfo      editinfo,v      notify,v

     図2 cvs init によって作成されるファイル
cvs init の init はサブコマンドである。CVS の各機能は、cvs コマンドのサブ コマンドで指定する。したがって、コマンドはすべて cvs というコマンドで始ま る。

(3)初期登録(インポート)

それでは、CVS で管理するファイルを作成する。なんらかのエディタを使って、 リスト1のようなファイルを作成しよう。

     リスト1 CVSで管理するファイル(example.c)

% cat example.c
#include 
/*
 *      This is CVS example file.
 *
 *      $Id$
 */
static char rcs_id[] = "$Id$";

int
main(int argc, char *argv[])
{
        printf("This is CVS example program\n");
}

この中にある $Id$ は、リビジョンを識別するためのマークである。最初のマーク はコメントの中に、次は文字列の中に記述している。通常はコメント内のもののみ でよいだろう。

このファイルの置き場所は重要である。新しいディレクトリを作成し、このファイ ルだけを置くこと。

% ls newdir
example.c
% cd newdir

次に cvs import コマンドを実行するが、このとき、カレントディレクトリにある ファイルとカレントディレクトリ以下のすべてのファイルが管理対象となる。 example.c を新しいディレクトリに入れたのは、このためだ。

cvs import コマンドの形式は図3のようになっている。

cvs import [-option] repository vendortag releasetag ...

カタカナにすると

cvs import [-option] リポジトリ ベンダータグ リリースタグ ...

     図3 cvs import コマンドの形式

リポジトリは貯蔵書、倉庫という意味で、これから管理しようとするファイル全体 を表す名称である。ソフトウェアの場合は、プログラム名とかモジュール名とかに なるであろう。

ベンダーは売る人、行商人という意味である。ブランチにつけられる名称であるが、 これは私にもよくわかっていないので、適当な名前をつけていただきたい。自分の 名前とか会社名でよいであろう。

リリースタグは、リリースにつけられるタグである。リリースの時点で意味を持つ が、最初であるから、initial とか start とか REL_0 でも良いだろう。タグに "."(ドット) は使えないので、release 3.1 とかを表現する場合には RELEASE_3_1 のようにする。

それでは、import コマンドを実行しよう。

% cvs import exampl myname start

そうすると、エディタが起動される。標準は vi である。環境変数 CVSEDITOR ま たは EDITOR に自分の好みのエディタを指定しておけば、それが起動される。

エディタの画面は、図4のような内容となっている。

CVS: ----------------------------------------------------------------------
CVS: Enter Log.  Lines beginning with `CVS:' are removed automatically
CVS: 
CVS: ----------------------------------------------------------------------

     図4 import コマンドでエディタが起動する

そこで、最後の行に

initial import.

などと入れること(図5)。

CVS: ----------------------------------------------------------------------
CVS: Enter Log.  Lines beginning with `CVS:' are removed automatically
CVS: 
CVS: ----------------------------------------------------------------------
initial import.

     図5 initial import. と書き込む

ファイルに書き込んでエディタを終わると、画面には図6のように表示される。

N exampl/example.c

No conflicts created by this import

     図6 エディタを終了する

これで、$CVSROOT ディレクトリを見てみると、

% ls -FC ~/cvsroot
CVSROOT/        exampl/

となって、リポジトリの名称と同じディレクトリが作成されている。そのディレク トリの下には、

% ls ~/cvsroot/example
example.c,v

このような新しいファイルがある。この,v とついたファイルが、RCS ファイルで ある。ファイルの属性はリードオンリーで修正できないようになっている。

(4)チェックアウト

CVS で、登録したファイルを取り出すことをチェックアウトという。まず、インポ ートしたのとは別のディレクトリに移動する。作業用のディレクトリであるので、 ここでは work という名前のディレクトリとする。

% cd ~/work
% cvs checkout exampl
cvs checkout: Updating exampl
U exampl/example.c

checkout には、インポートで指定したリポジトリ名を指定する。checkout が終わ れば、work ディレクトリの下にリボジトリ名のディレクトリが作成され、その下 に CVS というディレクトリと登録した example.c ファイルが置かれる。

% ls -FC ~/work
exampl/
% cd ~/work
% ls -FC exampl
CVS/            example.c
% cd exampl

example.c の内容を見るとリスト2のようになっている。

     リスト2 取り出した example.c

#include 
/*
 *      This is CVS example file.
 *
 *      $Id: example.c,v 1.1.1.1 2000/01/26 14:45:28 kogane Exp $
 */
static char rcs_id[] = "$Id: example.c,v 1.1.1.1 2000/01/26 14:45:28 kogane Exp $";

int
main(int argc, char *argv[])
{
        printf("This is CVS example program\n");
}

$Id$ が、ファイル名やリビジョン番号、日付、時間、作成者、状態に置き換えら れている。これらの情報でバージョンを識別することができる。では、これをコン パイルしてみよう。

% cc example.c

これで、a.out という実行形式が作成される。

次に、RCS コマンドである ident を実行する (図 7)。これは、rcs_id の中にあ る文字列が表示されたものである。a.out はバイナリファイルであるが、$Id とい うキーを見つけて ident が表示する。このようにリリースしたバイナリのバージ ョンも識別できるようになっている。

% ident a.out
a.out:
     $Id: example.c,v 1.2 1998/09/23 19:28:12 kogane Exp $

     図7 ident を実行する

$Id$ 以外にも置換されるキーワードがある。「その他の項目(1)置換されるキーワード」を参照のこと。

(5)コミット

それでは、リビジョン番号がどのように変化するか、試してみよう。example.c を リスト3のように修正する。

     リスト3 example.cを修正する

#include 
/*
 *      This is CVS example file.
 *
 *      $Id: example.c,v 1.1.1.1 2000/01/26 14:45:28 kogane Exp $
 */
static char rcs_id[] = "$Id: example.c,v 1.1.1.1 2000/01/26 14:45:28 kogane Exp $";

int
main(int argc, char *argv[])
{
        printf("This is CVS example program\n");
        printr("first change\n");
}

修正は work/exampl ディレクトリで行うが、そこで、バージョン管理システムに 取り込むためのコマンドであるコミットを実行する(注1)

(注1) cvsコマンドは、一部のサブコマンドを除いて、チェックアウトしたディレ クトリで行う必要がある。

ファイルがたくさんあり、どのファイルが変更されたかを知りたい場合には

% cvs -n update

を実行する。同じファイルを他の人が修正していないかどうかの確認もできる。

% cvs commit

エディタが起動されるので、変更理由を入力する(図8)。

CVS: ----------------------------------------------------------------------
CVS: Enter Log.  Lines beginning with `CVS:' are removed automatically
CVS: 
CVS: Committing in .
CVS: 
CVS: Modified Files:
CVS:    example.c 
CVS: ----------------------------------------------------------------------

     図8 変更理由を入力する

最後の行に

first change.

とかを追加し、ファイルを書き込み終了する。

変更理由には、EUC コードの日本語なら入力することができる。エディタの起動が 面倒なら、

% cvs commit -m 'first change.'

とすれば、エディタが起動されずに実行される。

ここで、example.c はリスト4のようになる。

     リスト4 コミット後の example.c

#include 
/*
 *      This is CVS example file.
 *
 *      $Id: example.c,v 1.2 2000/01/26 15:59:44 kogane Exp $
 */
static char rcs_id[] = "$Id: example.c,v 1.2 2000/01/26 15:59:44 kogane Exp $";

int
main(int argc, char *argv[])
{
        printf("This is CVS example program\n");
        printf("first change\n");
}

(6)ファイルの追加

バージョン管理にファイルを追加するには、cvs add コマンドを使用する。リスト5 は、example.c をコンパイルするための Makefile である。これを登録する(図9)。

     リスト5 Makefile

#
#       Makefile
#
#       $Id$
#
exampl: example.c
        cc -o $* example.c

% cvs add Makefile
cvs add: scheduling file `Makefile' for addition
cvs add: use 'cvs commit' to add this file permanently

     図9 Makefile を登録する

cvs commit を行って始めて登録される。

% cvs commit

エディタが起動され、図10のファイルが表示される。new add. を行の最後に追 加し、エディタを終わる。

CVS: ----------------------------------------------------------------------
CVS: Enter Log.  Lines beginning with `CVS:' are removed automatically
CVS: 
CVS: Committing in .
CVS: 
CVS: Added Files:
CVS:    Makefile 
CVS: ----------------------------------------------------------------------

     図10 commit 後エディタが起動する

Makefile はリスト6のようになる。

     リスト6 commit 後の Makefile

#
#       Makefile
#
#       $Id: Makefile,v 1.1 2000/01/26 16:02:49 kogane Exp $
#
exampl: example.c
        cc -o $* example.c

ここで、気がついたかもしれないが、import で初期登録したファイルのバージョ ンは 1.1.1.1 になり、次にバージョンアップすると 1.2 となる。バージョンアッ プを続けていくと、1.1.1.1→1.2→1.3→1.4 のようにバージョンがあがっ ていく。cvs add コマンドで登録すると最初のバージョンは 1.1 となり、これを バージョンアップしていくと、1.1→1.2→1.3→1.4 のようになる。

このように、最初のバージョンが 1.1.1.1 になるのがいやな人は、最初に何もフ ァイルが存在しないディレクトリで import を行い、checkout の後で add を行え ば、最初のリビジョン番号が 1.1 から始められることになる。これについては、 (7)で説明する。

add の逆に、管理からファイルを取り除くには、cvs remove コマンドを使用する。

(7)リビジョン番号 1.1 から始めるための登録

cvs init が終わった後、空のディレクトリを用意する。

% ls newdir
% cd newdir

そこで import コマンドを実行する。

% cvs import exampl2 myname start

次に別のディレクトリでチェックアウトを実行する。

% cd ~/work
% cvs checkout exampl2

チェックアウトしてもファイルを何も登録していないので、リポジトリ名のディレ クトリ (と CVS ディレクトリ)のみが作成される。次に、チェックアウトしたデ ィレクトリに移動する。

% ls -FC ~/work
exampl2/
% cd ~/work
% ls -FC exampl2
CVS/
% cd exampl2

そのディレクトリでファイル example.c を作成する。

% ls
example.c

この時点で add と commit を実行する(図11)。

% cvs add example.c
cvs add: scheduling file `example.c' for addition
cvs add: use 'cvs commit' to add this file permanently

% cvs commit -m 'new registration.'
cvs commit: Examining .
RCS file: /usr/home/kogane/cvsroot/exampl2/example.c,v
done
Checking in example.c;
/usr/home/kogane/cvsroot/exampl2/example.c,v  <--  example.c
initial revision: 1.1
done

     図11 add と commit を実行

example.c の内容はリスト7のように 1.1 版となっている。

     リスト7 add と commit 後の example.c

#include 
/*
 *      This is CVS example file.
 *
 *      $Id: example.c,v 1.1 2000/01/26 16:10:19 kogane Exp $
 */
static char rcs_id[] = "$Id: example.c,v 1.1 2000/01/26 16:10:19 kogane Exp $";

int
main(int argc, char *argv[])
{
        printf("This is CVS example program\n");
}

import コマンドの場合は、import を実行したディレクトリとその下に存在するす べてのファイルが登録される。ところが、add だとすべてのファイルやディレクト リを指定する必要がある。

次のように find と xargs コマンドを使えば、すべてのファイルを登録すること ができる。

% find . -print | xargs cvs add

ただし、ファイルが多い場合は時間がかかったりうまく実行できないかもしれない。 ファイル数が 100 個程度ならだいじょうぶだと思われる。ファイル数が多い場合 は、1 ファイル毎に cvs add を行う次のコマンドを使うとよいだろう。上記の通 り実行すると、図12のように表示される。これは、. ディレクトリを登録しよう とするためである。これを避けるためには、図13のようにして. を除けばよい。

cvs add: cannot add special file `.'; skipping

     図12 find . -print | xargs cvs add の実行結果

% find . -print | sed '/^\.$/d' | awk '{print "cvs add", $0}' | sh

     図13 . を取り除く

(8)リビジョン番号 1.1 から始めるための登録(その2)

cvs 使いのベテランなら、(7)の方法は面倒だと思われるだろう。そこで、もうひ とつの方法を紹介する。

% mkdir ~/work
% cd ~/work
% cvs checkout -l .
% mkdir exampl2
% cvs add exampl2
% cd exampl2
% cvs add example.c

cvs checkout -l . は、$CVSROOT のディレクトリだけをチェックアウトしている、 -l オプションは $CVSROOT 以下のディレクトリやファイルをリカーシブにチェッ クアウトしないオプションである。そこで、example2 ディレクトリを作成し、そ のディレクトリを add している。こうすることで、そのディレクトリ名でリポジ トリが作成されることになる。すなわち、$CVSROOT/example2 が作成される。あと は(7)と同様に各ファイルを add していけばよい。

(9)タグの設定

タグは、リリースを表す目的やスナップショットに付けるために使用される。 import サブコマンドでは、ベンダータグ、リリースタグを指定したが、これらは いずれも同じものである。

タグを設定するには、tag サブコマンドを使用する。このコマンドは、チェックア ウトを行ったディレクトリで実行すること。今日の日付が 2000年2月9日なら 日付を表すタグを用いて、

% cvs tag SNAP_000209

を実行することで、現在の時点のスナップショットのソースを表すタグとすること ができる。

また、リリース用のタグを設定する場合は、

% cvs tag REL_01
とかになるであろう。タグを設定するコマンドには、もう 1 つ rtag がある。こ れはリポジトリ(書庫)を指定してタグを付ける。
% cvs rtag REL_01 example

この rtag はリポジトリに対してタグを付けるので、チェックアウトしたディレク トリで実行する必要はない。

設定したタグをチェックアウトコマンドで指定すれば、 その時点のソースを再構成できる。

新しい別のディレクトリで図14のように行えば、そのディレクトリ下の exampl には SNAP_000209 や REL_01 とタグを付けた時点のソースが復元される。タグを 付けてチェックアウトしたファイルは、修正したりファイルを追加することができ ないので、チェックアウトを実行するよりは export コマンドを使用するほうがよ いだろう(図15)。export コマンドは checkout とほとんど同じであるが、cvs の管理ディレクトリ(CVS)が作成されない。

% cvs checkout -r SNAP_000309 exampl
% cvs checkout -r REL_01 exampl

     図14 タグを指定してソースを復元する

% cvs export -r SNAP_000309 exampl
% cvs export -r REL_01 exampl

     図15 export コマンドを使用する

(10)ブランチの指定

古いバージョンを元にして修正を行うためには、そのバージョンからのブランチを 指定する。tag、rtag コマンドのもうひとつの重要な機能は、ブランチを設定する ことである。tag、rtag コマンドに -b オプションを指定すると、指定したタグは ブランチタグとなる。

tag コマンドを使う場合は、まず古いバージョンでチェックアウトする。そして、 そのディレクトリで tag コマンドを実行する。

% cvs checout -r REL_01 exampl
% cvs tag -b REL_01_FIX

rtag コマンドを使えば、チェックアウトせずにタグを付けることができる(図16)。 REL_01_FIX のタグが設定されたなら、新しいディレクトリでチェックアウトを行う。

% cvs rtag -b -r REL_01 REL_01_FIX exampl

     図16 rtag コマンドを使用する

% cd ~/fixdir
% cvs checout -r REL_01_FIX exampl
% cd exampl

そこで、通常の修正や追加を行って、コミットすればファイルが修正される。

% cvs add NEWFILE ..
% cvs commit

ただ、ブランチの変更でファイルの追加コマンドである add サブコマンドを行う と、削除されたファイルが入る Attic ディレクトリに入れられる(図17)。そし て、このファイルは、「メインツリーに存在しないファイルである」ということで 削除されたファイルとして登録されてしまう。削除されたファイルというのが気に なるかもしれないが、そのような仕組みになっているということで納得するしかな い。このファイルは、メインツリーにマージする checkout -j オプションでマー ジすることにより、Attic から通常のディレクトリに移動する。「(13) マージ」 参照。

% ls -FC ~/cvsroot/exampl
Attic/          Makefile,v      example.c,v
% ls ~/cvsroot/exampl/Attic
NEWFILE,v

     図17 add サブコマンドによって Attic ディレクトリに入れられる

(11)ソースファイルの差分を見る

チェックアウトしたディレクトリで、どのようにファイルを修正したか知りたくな ることがある。そのようなときは、diff サブコマンドを使用する(図18)。これ は、14 行目に return 0; を追加した状態であることを示している。このような表 示は、diff コマンドの標準の表示と同じである。

% cvs diff example.c
Index: example.c
===================================================================
RCS file: /usr/home/kogane/cvsroot/exampl/example.c,v
retrieving revision 1.2
diff -r1.2 example.c
13a14
>       return 0;

     図18 diff サブコマンドを使用する

ファイル名を省略するとリポジトリすべてのファイルの差分が表示される(表示結 果は省略する)。

% cvs diff

diff サブコマンドでは、UNIX の diff コマンドと同様にコンテキスト diff(-c オプション) とか、ユニファイド diff(-u オプション) 形式が使える (図19)。 これらの表示では、ソース行の前後が表示されるので、差分が見やすくなる(注2)

(注2) 前に述べたように、cvs は diff コマンドを内蔵している。

% cvs diff -c example.c
Index: example.c
===================================================================
RCS file: /usr/home/kogane/cvsroot/exampl/example.c,v
retrieving revision 1.2
diff -c -r1.2 example.c
*** example.c   2000/01/26 15:59:44     1.2
--- example.c   2000/01/26 16:32:13
***************
*** 11,14 ****
--- 11,15 ----
  {
        printf("This is CVS example program\n");
        printf("first change\n");
+       return 0;
  }

% cvs diff -u example.c
Index: example.c
===================================================================
RCS file: /usr/home/kogane/cvsroot/exampl/example.c,v
retrieving revision 1.2
diff -u -r1.2 example.c
--- example.c   2000/01/26 15:59:44     1.2
+++ example.c   2000/01/26 16:32:13
@@ -11,4 +11,5 @@
 {
        printf("This is CVS example program\n");
        printf("first change\n");
+       return 0;
 }

     図19 -c オプションを使用する

この diff コマンドのように、常に -c オプションをつけて表示したくなるだ ろう。そのような場合には、ホームディレクトリの .csvrc ファイルに次のよう記 述すればよい。

% cat ~/.cvsrc
# # で始まる行はコメント
diff -c

これで、オプションのない diff コマンドを実行してもコンテキスト diff 形式で 表示される(図20)。

% cvs diff example.c
Index: example.c
===================================================================
RCS file: /usr/home/kogane/cvsroot/exampl/example.c,v
retrieving revision 1.2
diff -c -r1.2 example.c
*** example.c   2000/01/26 15:59:44     1.2
--- example.c   2000/01/26 16:32:13
***************
*** 11,14 ****
--- 11,15 ----
  {
        printf("This is CVS example program\n");
        printf("first change\n");
+       return 0;
  }

     図20 .cvsrc にオプションを指定した場合

一時的に .cvsrc のオプションを見て欲しくないときは、cvs の -f オプションを 使用する(図21)。

% cvs -f diff example.c
Index: example.c
===================================================================
RCS file: /usr/home/kogane/cvsroot/exampl/example.c,v
retrieving revision 1.2
diff -r1.2 example.c
13a14
>       return 0;

     図21 cvs の -f オプションを使用する

リポジトリに登録された最新のソースと比較するのではなく、ある特定のリビジョ ン番号のソースと比較する場合はそのリビジョン番号を指定する(図22)。-r 1.1 は -r1.1 のように詰めて記述してかまわない。

% cvs diff -r 1.1 example.c
Index: example.c
===================================================================
RCS file: /usr/home/kogane/cvsroot/exampl/example.c,v
retrieving revision 1.1
diff -c -r1.1 example.c
*** example.c   2000/01/26 14:45:28     1.1
--- example.c   2000/01/26 16:32:13
***************
*** 2,13 ****
  /*
   *    This is CVS example file.
   *
!  *    $Id: example.c,v 1.1 2000/01/26 14:45:28 kogane Exp $
   */
! static char rcs_id[] = "$Id: example.c,v 1.1 2000/01/26 14:45:28 kogane Exp $";
  
  int
  main(int argc, char *argv[])
  {
        printf("This is CVS example program\n");
  }
--- 2,15 ----
  /*
   *    This is CVS example file.
   *
!  *    $Id: example.c,v 1.2 2000/01/26 15:59:44 kogane Exp $
   */
! static char rcs_id[] = "$Id: example.c,v 1.2 2000/01/26 15:59:44 kogane Exp $";
  
  int
  main(int argc, char *argv[])
  {
        printf("This is CVS example program\n");
+       printf("first change\n");
+       return 0;
  }

     図22 特定のリビジョンとの比較

現在修正中のファイルではなく、特定のリビジョン番号同士を比較することもでき る。表示をユニファイド diff 形式として実行する(図23)。

% cvs -f diff -u -r1.1 -r1.2 example.c
Index: example.c
===================================================================
RCS file: /usr/home/kogane/cvsroot/exampl/example.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- example.c   2000/01/26 14:45:28     1.1
+++ example.c   2000/01/26 15:59:44     1.2
@@ -2,12 +2,13 @@
 /*
  *     This is CVS example file.
  *
- *     $Id: example.c,v 1.1 2000/01/26 14:45:28 kogane Exp $
+ *     $Id: example.c,v 1.2 2000/01/26 15:59:44 kogane Exp $
  */
-static char rcs_id[] = "$Id: example.c,v 1.1 2000/01/26 14:45:28 kogane Exp $";
+static char rcs_id[] = "$Id: example.c,v 1.2 2000/01/26 15:59:44 kogane Exp $";
 
 int
 main(int argc, char *argv[])
 {
        printf("This is CVS example program\n");
+       printf("first change\n");
 }

     図23 特定のリビジョン同士を比較する

(12)競合したファイルの修正

複数の人間で開発している場合、同じファイルを同時に複数の人間が修正すること がある。cvs update は、すでに他の人によってコミットされていれば、作業中の ファイルにマージする。競合が起きない修正であれば、そのままコミットすれば済 むが、競合が起きていれば手動で修正する必要がある。図24は、作業中のファイ ルのリビジョンが 1.2 で、すでに他の人によってリビジョン 1.3 としてコミット されていることを示している。cvs update した結果のファイルはリスト8のよう になる。

% cvs update
cvs update: Updating .
RCS file: /usr/home/kogane/cvsroot/exampl/example.c,v
retrieving revision 1.2
retrieving revision 1.3
Merging differences between 1.2 and 1.3 into example.c
rcsmerge: warning: conflicts during merge
cvs update: conflicts found in example.c
C example.c

     図24 競合が生じた場合

     リスト8 cvs update した結果

#include 
/*
 *      This is CVS example file.
 *
 *      $Id: example.c,v 1.3 2000/01/27 13:12:16 kogane Exp $
 */
static char rcs_id[] = "$Id: example.c,v 1.3 2000/01/27 13:12:16 kogane Exp $";

int
main(int argc, char *argv[])
{
        printf("This is CVS example program\n");
        printf("first change\n");
<<<<<<< example.c
        printf("second change\n");
        return 0;
=======
        return(0);
>>>>>>> 1.3
}

競合が生じた部分は、'<<<<<<<'、'======='、'>>>>>>>'のマークで囲まれてい る。この部分を手動で修正してからコミットを実行する。

(13)マージ

ブランチ REL01_FIX について、すべてのファイルについてメインツリーにマージ するなら checkout に -j オプションをつけて行う(図25)。

% cvs checkout -j REL01_FIX exampl3

     図25 checkout に -j オプションをつける

マージ時に競合が生じたならば、「(12)競合したファイルの修正」と同様に手 動で修正を行えばよい。

ブランチをマージした後、そのブランチに変更が加えられ、再びその変更をメイン ツリーにマージするようなことをしてはならない。

マージの仕組みと問題点を示すために、個々のファイルをマージする update -j オプションによるマージを説明する。cvs を利用する上からはこのようなマージは 行わないほうがよい。

あるファイル(abc.c)が、図26のようなリビジョンツリーになっていたとき、 ブランチで変更された部分をメインツリーにマージする(取り込む)ことが必要に なったとする。これは、update サブコマンドの -j オプションで行える。

      ┌─┴──┐
      │        │
      │ 1.2    │
      └─┬──┘
          │               ブランチ
      ┌─┴──┐         REL01_FIX
      │        ├────┐
      │ 1.3    │    ┌─┴──┐
      └─┬──┘    │        │
          │          │ 1.3.2.1│
          │          └─┬──┘
          │              │     
      ┌─┴──┐    ┌─┴──┐
      │        │    │        │
      │ 1.4    │    │ 1.3.2.2│
      └────┘    └────┘

     図26 リビジョンツリー

% cvs checkout exampl3
% cd exampl3
% cvs update -j REL01_FIX abc.c

または、リビジョン番号を指定して

% cvs update -j 1.3.2.2 abc.c

としてもよい。update で競合が生じたならば、「(12)競合したファイルの修正」 と同様に手動で修正を行う。

% cvs commit abc.c
でコミットを行えば、リビジョンツリーは図27のようになる。

      ┌─┴──┐
      │        │
      │ 1.2    │
      └─┬──┘
          │               ブランチ
      ┌─┴──┐         REL01_FIX
      │        ├────┐
      │ 1.3    │    ┌─┴──┐
      └─┬──┘    │        │
          │          │ 1.3.2.1│
          │          └─┬──┘
          │              │      
      ┌─┴──┐    ┌─┴──┐
      │        │    │        │
      │ 1.4    │    │ 1.3.2.2│
      └─┬──┘    └─┬──┘
          │              │      
          │<-------------┘
      ┌─┴──┐    
      │        │    
      │ 1.5    │   
      └────┘  

     図27 commit 後のリビジョンツリー

この後、前のツリーに図28のようなブランチの変更が加わる場合もある。

      ┌─┴──┐
      │        │
      │ 1.2    │
      └─┬──┘
          │               ブランチ
      ┌─┴──┐         REL01_FIX
      │        ├────┐
      │ 1.3    │    ┌─┴──┐
      └─┬──┘    │        │
          │          │ 1.3.2.1│
          │          └─┬──┘
          │              │      
      ┌─┴──┐    ┌─┴──┐
      │        │    │        │
      │ 1.4    │    │ 1.3.2.2│
      └─┬──┘    └─┬──┘
          │              │      
          │<-------------┤
          │              │      
      ┌─┴──┐    ┌─┴──┐
      │        │    │        │
      │ 1.5    │    │ 1.3.2.3│
      └────┘    └────┘

     図28 ブランチの変更

このとき図29のように行うとおかしなことになる。1.5 にはすでに 1.3.2.2 の 修正が取り込まれているからである。このような場合は、図30または図31のよ うにする。2 つ -j オプションが指定された場合は、最初の -j オプションから 次の -j オプションの間の変更をマージすることを意味する。

% cvs update -j REL01_FIX abc.c

     図29 cvs update を行うとおかしなことになる

% cvs update -j 1.3.2.2 -j REL01_FIX abc.c

     図30 cvs update に 2 つ -j オプションを指定する

% cvs update -j 1.3.2.2 -j 1.3.2.3 abc.c

     図31 cvs update に 2 つ -j オプションを指定するもう 1 つのやり方

図33のようにリビジョン番号が逆になった場合は、リビジョン 1.4 と 1.6 の間 の変更を削除する意味になる。

% cvs update -j 1.6 -j 1.4 xxx.c

     図33 変更を削除する

(14)変更履歴を見る

変更履歴を調べるためには log サブコマンドを使用する。

% cvs log example.c
RCS file: /usr/home/kogane/cvsroot/exampl/example.c,v
Working file: example.c
head: 1.2
branch:
locks: strict
access list:
symbolic names:
        start: 1.1.1.1
        myname: 1.1.1
keyword substitution: kv
total revisions: 3;     selected revisions: 3
description:
----------------------------
revision 1.2
date: 2000/01/26 15:59:44;  author: kogane;  state: Exp;  lines: +3 -2

first change.
----------------------------
revision 1.1
date: 2000/01/26 14:45:28;  author: kogane;  state: Exp;
branches:  1.1.1;
Initial revision
----------------------------
revision 1.1.1.1
date: 2000/01/26 14:45:28;  author: kogane;  state: Exp;  lines: +0 -0

initial import.
=============================================================================

     図34 log サブコマンドを使用する

ファイルを省略すれば、すべてのリポジトリについて表示する(表示結果は省略する)。

% cvs log

(15)誰がチェックアウトしているかを見る

チェックアウトの情報を表示するには、history コマンドを使用する(図35)。

% cvs history
O 01/26 16:31 +0000 kogane exampl  =exampl=  ~/work/*

     図35 history コマンドを使用する

同じリポジトリを他の人がチェックアウトしている状況を表示するには、 -a オプションを指定する(図36)。

% cvs history -a
O 01/26 16:31 +0000 kogane exampl  =exampl=  ~/work/*
O 01/16 03:53 +0000 friend exampl  =exampl=  ~/fwrk/*

     図36 history コマンドに -a オプションを指定する

(16)コミットの履歴を調べる

コミットの履歴を調べるのにも、history コマンドを使用する(図37)。

% cvs history -c example.c
A 01/26 15:59 +0000 kogane 1.1     example.c exampl == ~/work/exampl
M 01/26 16:31 +0000 kogane 1.2     example.c exampl == ~/work/exampl

     図37 history コマンドでコミットの履歴を調べる

ファイルを省略すれば、すべてのファイルのコミットの履歴について表示する(表 示結果は省略する)。

% cvs history -c

(17)status コマンド

status コマンドで、ファイルの状態を表示する(図38)。

% cvs status example.c
===================================================================
File: example.c         Status: Locally Modified

   Working revision:    1.2     Wed Jan 26 16:31:54 2000
   Repository revision: 1.2     /usr/home/kogane/cvsroot/exampl/example.c,v
   Sticky Tag:          (none)
   Sticky Date:         (none)
   Sticky Options:      (none)

     図38 status コマンドを使用する

ファイルを省略すれば、すべてのファイルのコミットの履歴について表示する(表 示結果は省略する)。

% cvs status

(18)cvs コマンドの形式を忘れたとき

cvs コマンドの形式を忘れたときは、-H オプションを使用する(図39)。

% cvs -H
Usage: cvs [cvs-options] command [command-options-and-arguments]
  where cvs-options are -q, -n, etc.
    (specify --help-options for a list of options)
  where command is add, admin, etc.
    (specify --help-commands for a list of commands
     or --help-synonyms for a list of command synonyms)
  where command-options-and-arguments depend on the specific command
    (specify -H followed by a command name for command-specific help)
  Specify --help to receive this message

The Concurrent Versions System (CVS) is a tool for version control.
For CVS updates and additional information, see
    Cyclic Software at http://www.cyclic.com/ or
    Pascal Molli's CVS site at http://www.loria.fr/~molli/cvs-index.html

     図39 -H オプションを使用する

cvs のオプションを知りたいときには図40のようにする。

% cvs --help-options
cvs: unrecognized option `--help-optiosn'
Usage: cvs [cvs-options] command [command-options-and-arguments]
  where cvs-options are -q, -n, etc.
    (specify --help-options for a list of options)
  where command is add, admin, etc.
    (specify --help-commands for a list of commands
     or --help-synonyms for a list of command synonyms)
  where command-options-and-arguments depend on the specific command
    (specify -H followed by a command name for command-specific help)
  Specify --help to receive this message

The Concurrent Versions System (CVS) is a tool for version control.
For CVS updates and additional information, see
    Cyclic Software at http://www.cyclic.com/ or
    Pascal Molli's CVS site at http://www.loria.fr/~molli/cvs-index.html

     図40 cvs のオプションの表示
サブコマンドがわからなくなったなら、図41のように指定する。

% cvs --help-command
CVS commands are:
        add          Add a new file/directory to the repository
        admin        Administration front end for rcs
        annotate     Show last revision where each line was modified
        checkout     Checkout sources for editing
        commit       Check files into the repository
        diff         Show differences between revisions
        edit         Get ready to edit a watched file
        editors      See who is editing a watched file
        export       Export sources from CVS, similar to checkout
        history      Show repository access history
        import       Import sources into CVS, using vendor branches
        init         Create a CVS repository if it doesn't exist
        log          Print out history information for files
        login        Prompt for password for authenticating server.
        logout       Removes entry in .cvspass for remote repository.
        rdiff        Create 'patch' format diffs between releases
        release      Indicate that a Module is no longer in use
        remove       Remove an entry from the repository
        rtag         Add a symbolic tag to a module
        status       Display status information on checked out files
        tag          Add a symbolic tag to checked out version of files
        unedit       Undo an edit command
        update       Bring work tree in sync with repository
        watch        Set watches
        watchers     See who is watching a file
(Specify the --help option for a list of other help options)

     図41 サブコマンドの表示

サブコマンドの形式やオプションを知りたいときは、-H に続けてサブコマンドを指 定する(図42)。

% cvs -H checkout
Usage:
  cvs checkout [-ANPRcflnps] [-r rev | -D date] [-d dir]
    [-j rev1] [-j rev2] [-k kopt] modules...
        -A      Reset any sticky tags/date/kopts.
        -N      Don't shorten module paths if -d specified.
        -P      Prune empty directories.
        -R      Process directories recursively.
        -c      "cat" the module database.
        -f      Force a head revision match if tag/date not found.
        -l      Local directory only, not recursive
        -n      Do not run module program (if any).
        -p      Check out files to standard output (avoids stickiness).
        -s      Like -c, but include module status.
        -r rev  Check out revision or tag. (implies -P) (is sticky)
        -D date Check out revisions as of date. (implies -P) (is sticky)
        -d dir  Check out into dir instead of module name.
        -k kopt Use RCS kopt -k option on checkout.
        -j rev  Merge in changes made between current revision and rev.
(Specify the --help global option for a list of other help options)

     図42 サブコマンドの形式/オプションの表示

その他の事項

(1)置換されるキーワード

表1のキーワードがソースファイル中に含まれていれば置換される。

表1 置換されるキーワード
キーワード 説明
$Author$ リビジョンを登録したユーザのログイン名。
$Date$ リビジョンが登録された日時 (UTC)。
$Header$ 標準的なヘッダ。RCS ファイルのフルパス名、リビジョン番号、 日時、作者、状態、ロック者 (ロックされている場合) が 埋め込まれる。CVS の場合、通常ファイルはロックされない。
$Id$ RCS ファイル名がフルパスでないことを除いて、$Header$ と同様。
$Locker$ リビジョンをロックしたユーザのログイン名 (ロックされてい ない場合は空)。CVS の場合、無意味。
$Log$ RCS ファイル名、リビジョン番号、作者、日時に続いて、 チェックイン時に与えたログメッセージが挿入される。
$Name$ ファイルをチェックアウトしたときに使用したタグ名。
$RCSfile$ パス名を含まない RCS ファイル名。
$Revision$ リビジョン番号。
$Source$ RCS ファイルのフルパス名。
$State$ リビジョンに cvs admin の -s オプションにより割り付けら れた状態。

コマンド形式

FreeBSD の man cvs または jman cvs を参照のこと。

ネットワークでの cvs 使用法

cvs は、ネットワークを介して使用することができる。

cvs リポジトリ (貯蔵書、倉庫)を 1 つの UNIX のサーバーで管理し、他の UNIX や Windows からサーバーにあるリポジトリに対してチェックアウトしたり、修正 結果をコミットすることができる。

サーバーに接続する方法として、次の 3 つの方法がある。

server モードの設定方法

ローカルなネットワークでは、ほとんど設定のいらない server モードが便利だろう。

(1)サーバー側の設定

サーバー側で、クライアントからの rsh が動くように設定しなければならない。 既存のログイン名を使用する場合はそのログイン名で設定するが、cvs 管理用のロ グイン名を設ける場合には通常の UNIX 管理方法で新しくユーザーを作成する必要 がある。

ここでは説明のため、ログイン名を cvsmng、ホームディレクトリを /usr/home/cvsmng とする。サーバーのサイト名 (ホスト名) を cvssite、クライ アントのサイト名を usrsite とする。

(2)クライアント側での cvs 環境の設定

クライアント側で rsh が動くようになれば、残る設定は1つだけである。csh ベースのシェルの場合なら、図44のようにする。毎回入力しないで済むように、 図44の setenv 文を .cshrc に入れておく。

% setenv CVSROOT :ext:cvsmng@cvssite:/usr/home/cvsmng/cvsroot

     図44 setenv文

ログインシェルが、sh、bash なら .profile に図45のように入力する。bash な ら図46のようにしてもかまわない。

CVSROOT=:ext:cvsmng@cvssite:/usr/home/cvsmng/cvsroot
export CVSROOT

     図45 .profile

export CVSROOT=:ext:cvsmng@cvssite:/usr/home/cvsmng/cvsroot

     図46 bashのときの .profile

(3)クライアントでの実行

サーバー側とクライアント側の設定が終わったら、cvs を実行するだけである。

(4)Secure shell (ssh)「安全シェル」を使った server モード

まず、ssh でサーバーのシステムにログインできるように環境を設定する必要がある。 ssh の環境ができたら、

% setenv CVS_RSH ssh

を追加する。もちろん、.cshrc に入れておくのがよいだろう。それ以外は、上記 の rsh の使用法とまったく同じである。ただし、コマンド実行時に ssh の RSA キーの入力が必要になる(図47)。

% cvs history
Enter passphrase for RSA key 'cvssite':   ← ここにキーを入力

     図47 RSA キーの入力

pserver モードの設定方法

(1)サーバー側の設定

ここでは、FreeBSD の設定について説明する。他の UNIX の場合は少し異なる部分 があると思われるが、ここでは触れないので、各自調べていただきたい。

ネットワークのサービス名の登録:

ほとんどの UNIX で同じと思われるが、/etc/services にサービス名を登録する。 図48の行を /etc/services に記入する。FreeBSD の場合は標準で入れられてい るので追加する必要はない。

cvspserver      2401/tcp   #CVS network server
cvspserver      2401/udp   #CVS network server

     図48 /etc/services に追加する

ネットワークのサービスプログラムの登録:

UNIX の起動時に /etc/rc の中で起動されるネットワークデーモン (inetd) にサ ービスプログラムを教える必要がある。FreeBSD の場合は /etc/inetd.conf に登 録する。CVSROOT ディレクトリが /usr/home/cvsmng/cvsroot なら、そのディレク トリを --allow-root に指定する。もちろん、ディレクトリを作成しておかなけれ ばならない (図49)。

cvspserver stream tcp nowait root /usr/bin/cvs cvs \
--allow-root=/usr/home/cvsmng/cvsroot pserver

注) \ で折り返しているが、実際は \ がなく1行に記入する。

     図49 ディレクトリを指定する

複数の CVSROOT が必要なら、--allow-root を複数指定する。サーバー側の設定は 以上である。

(2)クライアントでの cvs 環境の設定

上記の server モードと同様に、CVSROOT を設定する (図50)。 毎回入力しないで済むように、 図50の setenv 文を .cshrc に入れておく。

% setenv CVSROOT :pserver:cvsmng@cvssite:/usr/home/cvsmng/cvsroot

     図50 setenv 文

(3)クライアントでの実行

pserver モードでは、普通の cvs と異なって login コマンドを一度実行する必要 がある(図51)。 正常に終了すると、ホームディレクトリの下には .cvspass ファイルが作成される。

% cvs login
(Logging in to cvsmng@cvssite)
CVS password: *****             ← ログイン時のパスワードを入力する

     図51 login コマンドの実行

これで cvs が使えるようになる。たとえば、

% cvs history

必要がなければ、実行しなくてもかまわないが、 .cvspass ファイルから login 用のエントリを削除するには logout コマンドを使用する。

kserverモードの設定方法

kserverモードの設定方法については、各自で調べていただきたい。

その他

FreeBSD 固有の拡張

FreeBSD のソースは cvs で管理されているが、$Id$ ではなく $FreeBSD$ となっ ている。$FreeBSD$ を cvs のキーワードとして認識させるためには、CVSROOT 管 理ディレクトリに options ファイルを置く必要がある。このファイルの中身を次 のようにする。

tag=FreeBSD=CVSHeader

単に

% cp options ~/cvsroot/CVSROOT/

としてもよいが、この管理ディレクトリも cvs で管理したほうがよいと思われる。 このような場合、CVSROOT 管理ディレクトリも checkout することができる。 そこで、

% cvs checkout CVSROOT
% cd CVSROOT
% cvs add options
% cvs commit options

とする。しかし、これでは ~/cvsroot/CVSROOT/options,v ができるだけなので、 やはり

% cp options ~/cvsroot/CVSROOT/

は必要である。CVSup で FreeBSD のリポジトリを取得していて、 そのリポジトリを checkout する場合などに、 このような設定が必要になるのだが、それ以外の場合には必要ない。 このような仕組みになっているということだけを理解すればそれで十分だろう。
新注)
CVSROOT のファイルをチェックアウト状態にするためには、 checkoutlist にファイル名を追加する。この場合は checkoutlist に options のファイル名を追加して、checkoutlist 自身をコミットすればよい。

options ファイルが

tag=FreeBSD=CVSHeader
tagexpand=iFreeBSD

となった場合は、$FreeBSD$以外は展開されない。古い$Id$を残す場合には、この ように指定する。

tcsh での cvs コマンドの利用

tcsh などの csh 系のシェルを使っているユーザーは、 コマンド名の補完機能を良く使用することだろう。 cvs では、機能のほとんどがサブコマンド形式になっている。 しかし、補完されるのは cvs だけなので、 サブコマンドのつづりを間違えることがよくある。 図52のような alias を作ることもできるが、 tcsh の complete を使用するとことで、 第一引数のサブコマンドが補完できるようになる。 図53のコマンドを ~/.cshrc か ~/.tcshrc に記述しておくとよい。

alias cvs_checkout      cvs checkout
alias cvs_commit        cvs commit

     図52 alias を使用する

complete cvs 'c/--/(help help-options help-commands help-synonyms)/' \
        'c/-/(H Q q r w l n t v b T e d f z a s)/' \
        'p/1/(add admin annotate checkout commit diff \
        edit editors export history import init log login logout rdiff \
        release remove rtag status tag unedit update watch watchers)/'

    図53 complete を使用する

コミットしたらメールを送る

複数の人間でソフトウェアを開発している場合に、 誰かがファイルの修正を (commit) したら、 全員にメールで通知できれば便利だろう。CVSROOT の loginfo を用いれば実現できる。 loginfo の最後は図54のようになっている。

#   s = file name
#   V = old version number (pre-checkin)
#   v = new version number (post-checkin)
#
# For example:
#DEFAULT (echo ""; id; echo %s; date; cat) >> $CVSROOT/CVSROOT/commitlog
# or
#DEFAULT (echo ""; id; echo %{sVv}; date; cat) >> $CVSROOT/CVSROOT/commitlog

     図54 loginfo の最後の部分

この部分を、たとえば図55のようにする。mailing_list_members は /etc/aliases 等で定義しておくこと。

DEFAULT $CVSROOT/CVSROOT/log_accum.pl -m mailing_list_members

     図55 loginfo の最後を変更する

log_accum.pl は FreeBSD の場合 /usr/share/examples/cvs/contrib/log_accum に置いてあるので、図56のようにしてコピーしておこう。

% cp /usr/share/examples/cvs/contrib/log_accum ~/cvsroot/CVSROOT/log_accum.pl 

     図56 log_accum.pl をコピーする

ところが、log_accum.pl はこのままでは動作しない。そこで、簡単に図57 のようにしておこう。これだと Subject がつかないので図58 のようにしたいかもしれない、しかし % は 1 回しかスキャンされないので、 Subject は %s commit となってしまう。また、 コメントに日本語を使う場合は図59のように nkf でフィルタリングするとよい。

DEFAULT (echo ""; id; echo %{sVv}; date; cat) | /usr/bin/mail mailing_list_members

     図57 log_accum.pl の設定

DEFAULT (echo ""; id; echo %{sVv}; date; cat) | /usr/bin/mail -s "%s commit" mailing_list_members

     図58 Subject をつけたい

DEFAULT (echo ""; id; echo %{sVv}; date; cat) | nkf -j | /usr/bin/mail -s "CVS commit" mailing_list_members

     図59 nkf でフィルタリングする

うーむ。誰か log_accum.pl を動くようにしてほしい :-)

これらの変更は、options ファイルと同様に checkout CVSROOT として cvs commit で修正を行うほうがよいだろう。もう 1 つの方法は、cvs watch コマンドと CVSROOT/notify ファイルで行うものである。この場合は、 対象となるファイルを指定する。

他で作成された cvs ファイルを取り込むには

,v ファイルを含めて、リポジトリ以下のファイルがあるなら、 単に CVSROOT 以下にコピーすればよい(図60)。

% cp -r othercvs ~/cvsroot/

又は

% tar cf - othercvs | (cd ~/cvsroot | tar -xf - )

     図60 CVSROOT 以下にコピーする

この後、適当なディレクトリで

% cvs checkout othercvs

を行えばよい。

古いリビジョン番号のソースを取り出したい

以前のリビジョン番号のソースを取り出すには、update サブコマンドを使用する。 このコマンドは、checkout したディレクトリで実行すること。

% cvs update -r1.1 example.c

これだと、現在のファイルにリビジョン 1.1 のファイルが上書きされる。上書きを 防ぐには、-p オプションを使って標準出力に出力するようにする(図61)。

% cvs update -p -r1.1 example.c >out.example.c

     図61 -p オプションを使う

現在のファイルに上書きされた場合、復元するには

% rm example.c
% cvs update example.c

とすればよいように思える。しかし、example.c ファイルはリビジョン 1.1 のままである。status サブコマンドを実行すると図62のようになる。

% cvs status example.c
===================================================================
File: example.c         Status: Up-to-date

   Working revision:    1.1     Thu Jan 26 16:10:19 2000
   Repository revision: 1.1     /usr/home/kogane/cvsroot/exampl/example.c,v
   Sticky Tag:          1.1
   Sticky Date:         (none)
   Sticky Options:      (none)

     図62 status サブコマンドの出力

Sticky Tag(張り付きタグ)が 1.1 となっているので、

% cvs update -A example.c

を実行する。-A オプションは Sticky Tag(張り付きタグ) や Sticky Date(張り付 き日付)、Sticky Options(張り付きオプション) を取り去ってメインツリーの先頭のリビジョンに戻す。

ただし、Sticky Tag(張り付きタグ) は checkout したディレクトリのみで有効なので、 他の場所でリポジトリを checkout すれば、最新のリビジョンがチェックアウトされる。

修正を取り消したい

コミットをした後、この修正を取り消したいと思うことがよくある。SCCS にも、 直前の修正を取り消す rmdel コマンドがある。

cvs では、このような取り消しを行う直接のサブコマンドは用意されていないが、 admin サブコマンドで行うことができる。

ただし、複数の人間で開発している場合には、他の人間が update や checkout をしていると不整合が起こるので、 そのような場合は前と同じバージョンのソースでもう一度 commit するほうがよいだろう。

コミットの結果のリビジョンが 1.4 ならば、次のように行う。

% cvs admin -o1.4 example.c

リビジョンは直前のものでなくても削除できる。危険なコマンドなので十分注意し て実行すること。

% cvs admin -o1.3:1.4 example.c

のようにして、範囲を指定することもできる。

特定のリビジョン番号を削除してもコミットした結果のファイルは更新されないので、 「古いリビジョン番号のソースを取り出したい」で説明した update サブコマンドを使うか、1 つ上のリポジトリ名のディレクトリに移り、 checkout を実行すれば前のバージョンのソースが得られる。

% cvs update -A example.c

または

% cd .. 
% cvs checkout exampl

バイナリファイル

ソースファイルと同時にバイナリファイルも一緒に管理したいことがある。 このようなときは、次のように -kb オプションをつけて add を実行すればよい。

% cvs add -kb binary_file

patchファイルを作成する

patch コマンドの入力になるファイルを作成することができる。 図63のようにすると、 リリースタグ REL01 からメインツリーの先頭のバージョンとの差分が patch 形式で出力される。当然、バージョンを 2 つ指定して実行することもでき る(図64)。

% cvs rdiff -r REL01 exampl >exampl.patch.diff

    図63 patch を出力する

% cvs rdiff -r REL01 -r REL02 exampl >exampl.patch.diff

     図64 バージョンを 2 つ指定して patch を出力する
図65のように、標準ではコンテキスト diff の形式で patch が作成される。

% cvs rdiff -r REL01 -r REL02 exampl
cvs rdiff: Diffing exampl
Index: exampl/example.c
diff -c exampl/example.c:1.1 exampl/example.c:1.4
*** exampl/example.c:1.1        Wed Feb  9 21:54:34 2000
--- exampl/example.c    Thu Feb 10 00:42:29 2000
***************
*** 2,13 ****
  /*
   *    This is CVS example file.
   *
!  *    $Id: example.c,v 1.1 2000/01/26 14:45:28 kogane Exp $
   */
! static char rcs_id[] = "$Id: example.c,v 1.1 2000/01/26 14:45:28 kogane Exp $";
  
  int
  main(int argc, char *argv[])
  {
        printf("This is CVS example program\n");
  }
--- 2,16 ----
  /*
   *    This is CVS example file.
   *
!  *    $Id: example.c,v 1.4 2000/01/27 15:42:29 kogane Exp $
   */
! static char rcs_id[] = "$Id: example.c,v 1.4 2000/01/27 15:42:29 kogane Exp $";
  
  int
  main(int argc, char *argv[])
  {
        printf("This is CVS example program\n");
+       printf("first change\n");
+       printf("second change\n");
+       return 0;
  }

     図65 コンテキスト diff 形式の出力

diff サブコマンドと同様に、.cvsrc に

% cat ~/.cvsrc
rdiff -u

と記入するか、オプションで -u を指定すればユニファイド diff の形式で出力さ れる(図66)。

% cvs rdiff -u -r REL01 -r REL02 exampl
cvs rdiff: Diffing exampl
Index: exampl/example.c
diff -u exampl/example.c:1.1 exampl/example.c:1.4
--- exampl/example.c:1.1        Wed Feb  9 21:54:34 2000
+++ exampl/example.c    Thu Feb 10 00:42:29 2000
@@ -2,12 +2,15 @@
 /*
  *     This is CVS example file.
  *
- *     $Id: example.c,v 1.1 2000/01/26 14:45:28 kogane Exp $
+ *     $Id: example.c,v 1.4 2000/01/27 15:42:29 kogane Exp $
  */
-static char rcs_id[] = "$Id: example.c,v 1.1 2000/01/26 14:45:28 kogane Exp $";
+static char rcs_id[] = "$Id: example.c,v 1.4 2000/01/27 15:42:29 kogane Exp $";
 
 int
 main(int argc, char *argv[])
 {
        printf("This is CVS example program\n");
+       printf("first change\n");
+       printf("second change\n");
+       return 0;
 }

     図66 ユニファイド diff 形式の出力

Windows での cvs の使用

Windows 版の cvs は、

ftp://download.cyclic.com/pub/cvs-1.10/windows/cvs-1.10-win.zip

で入手できる。これを zip 展開すれば、実行形式のファイルが得られる。 zip ファイルを展開する Windows 用のコマンドは知らないが、 FreeBSD なら unzip という package がある。

内容は FAQ、NEWS、README、cvs.exe、cvs.html、patch.exe、win32gnu.dll ファイルである。

Windows 単体でも使用できるが、ここでは pserver モードでの使用法を説明する。 server モードのほうが設定等は簡単であるが、Windows で正常に動作する rsh コマンドを入手できないので、取り上げない(注3)

(注3) ssh は正常に動作するが、説明が長くなるので省略する。

Windows では、DOS 窓ですべての操作を行う。cvs.exe と win32gnu.dll を実行 PATH のあるディレクトリに移動し、環境変数を設定すれば動作する。

pserver モードの場合の設定は、図67のようになる。HOME は適当なディレクトリを指定すること。

set CVSROOT=:pserver:cvsmng@uxsite:/usr/home/cvsmng/cvsroot
set HOME=c:\MYNAME

     図67 pserver モードの設定

Windows から UNIX のサーバーを使用する場合に心配なことがひとつある。それは、 Windows のテキストファイルの行末が \r\n(CR+LF) で UNIX では \n(LF) だということである。しかし、これは cvs で自動的に変換されるので、問題はない。 ただし、日本語コードは変換されない。Windows でシフト JIS コード、 UNIX 側は EUC コードとするパッチ(注4)を筆者が作成したので、 必要であれば利用されたい。これについては、「Windows での cvs コンパイル」で説明する。 UNIX 側の cvs コマンドは特に変更する必要はない。

(注4) 付録 CD-ROM の添付ファイル cvs.1.10.diff

Windows での cvs コンパイル

cvs のソースは

ftp://download.cyclic.com/pub/cvs-1.10/cvs-1.10.tar.gz

から入手できる。

(注)現在は ftp://ftp.cvshome.org/pub/cvs-1.10/cvs-1.10.tar.gz です。

現在の最新版は cvs-1.10.8.tar.gz である。[(注)現在最新版は cvs-1.11.5.tar.gz である。]

しかし、 コンパイルを試みたところできなかったので、ここでは 1.10 で説明する。 コンパイルは Visual C++ 5.0 で行った。本来は、cvs-1.10 ディレクトリにある cvsnt.mak を使って、

C> nmake /f cvsnt.mak

で、コンパイルできるはずである。しかし、cvsnt.mak に間違いがあるためコンパイルできない。 付録 CD-ROM に含まれるファイル cvs.1.10.diff にパッチが入っているので、 Windows でパッチをあてるか、UNIX でパッチをあてたファイルを Windows にコピーして使用してほしい。

C> nmake /f cvsnt.mak

を行うと、WinDebug\cvs.exe に cvs コマンドが作成される。 リリースモードでコンパイルするには、cvsnt.mak の

CFG=cvsnt - Win32 Debug

の部分を

CFG=cvsnt - Win32 Release

にすると、WinRel\cvs.exe にコマンドが作成される。

ダウンロードした cvs.exe では、Windows 上で commit ログメッセージにシフト JIS 日本語コードが使えないのだが、Visual C++ 5.0 で再コンパイルすると使え るようになる。これは、うれしい副作用だ。


改版履歴
平成16年(2004年)01月12日 (月)
options,v ファイルに関して checkoutlist ファイルの説明をする新注を追加。
平成16年(2004年)01月15日 (木)
索引を追加。

有限会社 小金丸コンピュータエンジニアリングサービス
小金丸信幸