cvs - バージョン管理ツール:


cvs (Concurrent Versions System) を利用すると古いファイル(通常テキストファイル)を保存しておくことができ、楽に元に戻したり、最新との差異を表示したりできたり、いつ、だれが、なぜ、ファイルを変更したのかのログも保存しておくなど、バージョン管理をすることができます。 複数人が同時に同じファイルを編集してしまった際の対策もよくできており、グループでプログラム作成をする時によく利用されます。もちろん、1人の場合でも便利です。

すべて書くと、逆にわかりづらくなるので、実際に使用する際にとりあえず必要なものを説明していきます。 すべての機能を知りたい方はCVS--Concurrent Versions System (in Japanese) のページを読むとよいかと思います。cvs のマニュアルですのでここにすべてが詰まっています(わかりやすいかどうかはおいておいて)。

Table of Contents

基本 Edit

まず cvs コマンドの書式は以下の様になります:

cvs [ global_options ] command [ command_options ] [ command_args ]

初期設定 Edit

まず、環境変数 CVSROOT と CVSEDITOR を設定しておいてください。

  • csh
    % setenv CVSROOT リポジトリとするディレクトリ
    % setenv CVSEDITOR エディタのフルパス
  • bash
    % export CVSROOT=リポジトリとするディレクトリ
    % export CVSEDITOR=エディタのフルパス

リポジトリとはバージョン管理の対象となるすべてのファイルやそのコメントの情報を格納しておく格納庫 (Repository) です。$HOME/project とでもしておくとよいと思います*1

これを .cshrc または .bashrc 等の設定ファイルに記述しておくとよいでしょう。 CVSEDITOR を設定していな場合はシステムのデフォルトエディタ(普通は vi) が利用されます。 CVSROOT は cvs の [global_option] -d で指定することも可能です。設定しておいた方が楽です。

以下、これで進めます。 このディレクトリは作っておいてください。

% mkdir $HOME/project

その後

% cvs init

と実行してリポジトリを初期化します。

プロジェクトの登録 Edit

% cvs import -m [ comment ] [ project_name ] [ vender_tag ] [ release _tag ]

のようにします。カレントディレクトリ以下のファイルをプロジェクトとして登録します。これはプロジェクトを作成する初回毎だけの実行となります。 import は略して im と書くこともできます。

  • [ project_name ] はまさしく、プロジェクトの名前です。これは今後開発する際の、デフォルトのディレクトリ名になります。作成するプログラムの名前でもいれておきましょう。ちなみに、"test/othello" のように階層化を利用することもできます。
  • [ vender_tag ] は vender branch に与えるタグ名です。とりあえず branch(枝) のことは気にしなくてよいです。vender_tag と言っているぐらいですので、開発元の名前をいれておくとよいと思います。
  • [ release_tag ] は登録するファイルのリビジョンを一括して扱うタグ名です。import では vender branch 上に登録されるので、vender1_0_0 のように自分はしています。ちなみにリビジョン番号とはバージョン番号のようなものです。よくあるバージョン2などのことではなく CVS が自動的に付ける番号ですので、それと区別するためにリビジョンと呼ばれています。
  • コマンドオプション -m [ comment ] でコメントを指定しなかった場合、 CVSEDITOR で設定したエディタが起動し、コメントを書きこむことになります。その際は CVS: と先頭にある行の下に書きます。 どういうソフトなのかの説明を書くことになると思います。

プロジェクトのロード Edit

% cvs checkout [project name]

指定したプロジェクトをカレントディレクトリに呼び出します。 checkout は省略して co とすることも可能です。 [project name] のディレクトリが作成されます。

% cvs checkout -d [dir name] [project name]

のように [command_option] -d を使用すると指定したディレクトリ名で作成することができます。

checkout で CVS 情報も取得するので、登録した人も実行しておかなければいけません。 その際、プロジェクト名とローカルのディレクトリ名が同じ場合、 上書きするよう checkout したいところですが、Conflict がおきたりして具合が悪いので、 別名のディレクトリに checkout するか、一度ローカルのディレクトリを消去する必要があります。

ここでいう CVS 情報というのは各ディレクトリに作られる CVS/Entries, CVS/Repository, CVS/Root などのファイル内の情報のことです。

% cvs co -r [branch_name]

これはOK

% cvs co -r [tag_name]

だとロードはできますが、その後 commit できなくなります。-A がどうとかなんとか?

プロジェクトの更新 Edit

ファイルを修正した後、

% cvs commit

を実行すると修正したファイルを新バージョンとして登録できます。 commit は省略して ci とすることも可能です。 この時、カレントディレクトリはプロジェクトを呼び出したディ レクトリにしておいてください。 CVSEDITOR で設定したエディタが起動してコメントを書きこむことになります。 ここでも

% cvs commit -m [comment]

のようにしてコマンドラインでコメントを指定することもできます。 コメントには何を修正したか、追加したかなどを書き込むことになると思います。 また、

% cvs commit -m [comment] [files ....] 

のようにして指定したファイルだけを更新することもできます。

ファイルの追加 Edit

新規のファイルを追加する場合は

% cvs add [files ...]

を実行しておいてから commit を実行します。

% cvs add *

のようにワイルドカードを使用することもできます。 バイナリファイルの場合は

% cvs add -kb [files ...]

のように追加します。このときの commit のコメントには「このファイルを追加」のように書いておくことになると思います。

ファイルの削除 Edit

逆に削除する場合は、

% cvs remove [files ...]

と実行しておいてから commit します。この場合はワーキングディレクトリのファイルは削除されませんので、そちらも削除したい場合は rm コマンドで削除します。または、

% cvs remove -f [files ...]

のように実行すると、削除予定に組み込むと共に、ワーキングディレクトリのファイルも削除してくれます。
あらかじめファイルを削除しておくと、

% cvs remove

とするだけで自動的に削除すべきファイルを識別して、予定に組み込んでくれます。 commit するのを忘れずに。

ファイル名の変更 Edit

一度、remove して add しなおすしかありません。

% mv [oldfile] [newfile]
% cvs remove [oldfile]
% cvs add [newfile]
% cvs commit

このときリビジョンが最初に戻ってしまうので、気になる方は

% cvs commit -r [revision] [newfile]

のようにしてリビジョン番号を指定して commit してください。 ファイルを指定しないと、すべてのファイルのリビジョンが変更されてしまうので注意してください。

衝突がおこった場合 Edit

cvs の本領発揮です。 commit をしようとすると

cvs commit: Up-to-date check failed for [filename]

のような表示がされることがあります。 これは他の人がすでにCVSを更新していて、自分が編集していたファイルが最新のものではなかったときに生じます。このようなときは

% cvs update

と実行して、CVS 内の最新ファイルとローカルファイルをマージします。 ローカルファイルのリビジョンも最新のものになります。

%%少し詳しく書くと、

% diff3 -M [ローカルファイル] [元となったリビジョンのファイル] [最新リビジョンのファイル]

と同じような動作をします。%% [ローカルファイル] に、[元となったリビジョンのファイル] から [ローカルファイル] への変更点と、[元となったリビジョンのファイル] から [最新リビジョンのファイル] への変更点をマージするような動作です。

%%予備知識として書くと

% cvs update -jBASE -jHEAD

と同等です。HEAD は最新リビジョンに与えられるタグです。 [元となったリビジョンのタグ] を設定していない場合は、すべて一度にやるのは無理です。 タグについては別のところで説明します。%%

このとき、自分と相手が同じ部分を変更していて衝突(conflict)が起こる場合があります。単純にマージできた場合は

M [filename]

のように表示されますが、conflict が起こった場合は

C [filename]

のように表示されます。これらの動作が起こった場合、

.#[filename]

のようなバックアップファイルが作成されます。

コンフリクトがおきたファイルを開くと

 <<<<<<< A
 lines from A
 =======
 lines from B
 >>>>>>> B

のような部分ができてしまっていると思います。 こうなると仕方がないので手動でちくちく直す必要があります。 このようにして修正しおわったら改めて commit します。

どのファイルでコンフリクトがおきたのかは、簡易的に

% grep '<<<<<' -r .

のようにして探すこともできなくはないです。

ローカルファイルの状態の確認(最新か確認する) Edit

% cvs status [files ...]

でファイルのリビジョンを確認できます。 status は st と省略することも可能です。 [files ...] を1つも指定しなければカレントディレクトリ以下すべてのファイルに対して表示します。

Status: Up-to-date

となっていれば、最新版です。

% cvs status -v [files ...]

のようにオプション -v でそのファイルが持っているタグ名とそれに対応するリビジョン番号、ブランチ番号も見ることができます。

ログの確認 Edit

% cvs log [files ...]

で指定したファイルのログ(いつ特定のリビジョンが作られたか、またそのときのコメント)を参照できます。 ファイルを指定しない場合はすべてのファイルに関して表示されます。

発展 Edit

タグ Edit

% cvs tag [tag_name]
% cvs tag -d [tag_name]

Edit

% cvs tag -b [branch_name]

カレントディレクトリにあるリビジョンにたいして

% cvs rtag -r [tag_name] -b [branch_name]

オプション -r で指定したタグに対してブランチを作成。 ブランチ名も結局はタグ名です。

% cvs rtag -r [branch_name] -b [branch_name]

とすれば -r で指定したブランチの最新リビジョン。

% cvs checkout -r [branch_name]

でそのブランチの最新がおちてくる。 そのブランチの古いやつを取得するときは?

sourceforge Edit

sourceforge とはオープンソースソフトウェア開発者御用達サイトです。 sourceforge に登録したプロジェクトでの cvs の使い方オフィシャルドキュメントはこちら。

開発サイトのおっかけ Edit

なんか変

プログラムを自分なりに改造した場合、 CVSを用いて楽にそのプログラムの次のリリースにも同じ修正を加える方法です。

まず最初は開発サイトのものをローカルCVSに import します。

% cd pukiwiki
% cvs im -m "PukiWiki1.4.2" pukiwiki trunk r1_0_1

このとき内部的には各ソースファイルのリビジョンは 1.1.1.1 (r1_0_1)に、そのファイルが所属している枝のリビジョンは 1.1.1 (trunk)になっているはずです。checkout 後に、

% cvs status -v

で確認できます。とにもかくにも checkout します。

% cvs co pukiwiki

改造をしたら commit しておきます。

% cvs ci

このとき修正のあったファイル自身のリビジョンは 1.2 になっているはずです。 このときリビジョンの順番的には 1.1.1.1 (r1_0_1) → 1.1 → 1.2 のようになっています。

開発サイトの配布物が更新されたら、最初のように import で登録します。 ただしリリースタグは変えます。

% cvs im -m "PukiWiki1.4.3" pukiwiki trunk r1_0_2

ファイルがローカルな修正をされていた場合、おそらく conflict が起こっている旨を伝え、checkout -j を使用してマージするように促してきます。 このとき内部的にはソースファイルのリビジョンは 1.1.1.2 (r1_0_2) に、そのファイルが所属している枝のリビジョンは 1.1.1 (trunk)になっているはずです。 このときリビジョンの順番的には 1.1.1.1 (r1_0_1) → 1.1 → 1.2 → 1.1.1.2 (r1_0_2) のようになっています。

そして、次のコマンドによりマージします。

% cvs co -jr1_0_1 -jr1_0_2 pukiwiki

これは

% cvs co -j1.1.1.1 -j1.1.1.2 pukiwiki

と同等です。 これにより CVS 内の各ファイルの最新リビジョン (おそらく1.2) に対し、 1.1.1.1 (r_1_0_1) から 1.1.1.2 (r1_0_2) への変更点をマージしたファイルを作成します。 つまり、改造したものに、開発サイトの旧バージョンから新バージョンへの変更点をマージするということになります。

この際修正箇所がかぶってしまった場合は conflict が起こり、ファイル中に

  <<<<<<< A
  lines from A
  =======
  lines from B
  >>>>>>> B

のような部分ができてしまっていると思います。

% grep '<<<<<' -r [dir1]

とでもして探し、ちくちく手動で直してください。修正後 commit しておきましょう。

% cvs ci

1.1.1.1 (r1_0_1) → 1.1 → 1.2 → 1.1.1.2 (r1_0_2) → 1.3 のようになります。



*1 これは :local:$HOME/project と同じ意味です。サーバーを用いる場合は :[server name]:[repojitory] のようにサーバー名が必須になります。
xrea