日常的なCVSの利用

概要

複数の人でプロジェクトを組む時に,同じファイルを複数の人が同時に 編集してしまって,一人分の変更しか反映されなかったというような経 験はないであろうか. また、自分が開発しているアプリケーションが複数のシステム上で 実行されていて、 どのプログラムが一体どの版であったのか、 というのがわからなくなっている、 というような状況は無いだろうか。 そのような状況を改善/解決してくれるのが CVSで ある.これは,Windowsのファイル共有や,FTPを利用していている場面で,それらに とってかわるものである.

CVSは,レポジトリというところに集中管理されているファイルをおき それから個人個人が取り出した作業用のディレクトリ(ワーキングディレクトリ)に対してそれ ぞれの人が作業し,複数の人が独立して同時に作業する環境を 実現するものである.個人個人が作業した情報は差分情報として,レ ポジトリにとりこまれ,そして,各ワーキングディレクトリには,それぞれcvs updateをすることによりレポジトリから差分がマージされる.同時に作 業した場合にどうしても両方の変更を両立できないという場合にはコン フリクトが起きるが,それ以外の場合では,同時に複数の人がファイル の別の箇所で作業していても,その作業の成果は失われない.

CVSは常にネットワーク接続できている中央サーバを仲介役とした 集中管理のもと,データを共有しながら更新するのに便利なシステムである. コンフリクトの発生は困りものだが, その欠点はIRCやメーリングリスト等の別の情報交換手段を利用して, メンバ間の調整をすることで補完する事ができる. 少なくとも最低限の事ができるようになるために,このメモを作成する.

CVSを便利に利用できるものとしてまず考えられる用途としては,ウェブページの管理と, プログラムのソースコードの管理である. 特にプログラムのソースコードの場合,変更した履歴が自明になるということは, 変更管理の観点から重要である. 複数の人で管理するのでなくても,CVSなどで管理する利点があるだろう. プログラムのソースコードの最新版がcvs updateコマンド入力 だけで得られるという利便性を提供する. 例えば、複数のHPCクラスタサーバを利用してプログラムの実行が 行われているとする、 手もとのシステムでソースコードを変更し, commitした変更は、 複数のシステムで、cvs updateするだけで 反影する。複数のシステムに対して、手動で scp や、 ftp や、samba 等でコピー するより、確実である。

作業フロー

cvsを利用している場合の一般的な作業フローを説明する. 通常の作業はこのようなフローになるだろう.

ある一日の作業例

cd ~/cvs-checkedout/webpage
cvs update
vi index.html #で編集
cvs ci -m "updated the description" index.html

vi XXX.html # 新しいファイルを編集
cvs add XXX.html # レポジトリに追加
cvs ci -m "New file added" XXX.html # その追加を反映

# でも, 気に入らないので削除
rm XXX.html
cvs remove XXX.html
cvs ci -m "Removed" # その追加を反映
    

これは,あるviユーザ(Windows用のエディタのユーザも 同様の方針で作業する事になる.)の作業履歴である.emacsのユーザは emacs用の環境を利用できる.

コマンドライン

まず,CVSをインストールするには,apt-get install cvs

まず,コマンドラインで利用できるCVSというコマンドの動作の概要に ついて解説する.詳しくはinfo cvsをみてほしい. 初期設定としては,まず,.bash_profileを編集するなどして 環境変数CVS_RSHの値をsshにする.そ して,CVSROOTを, :接続方法:ユーザ名@サーバ名:サーバ上のレポジトリのパス というように設定する.sshをなぜextと呼ぶのかは不明だが, sshの場合は接続方法はextである. ちなみに,CVSROOTは,自分のマシン上にある場合は,単にそのパスを 指定するだけで良い. .bash_profileの例を示す.

export CVS_RSH="ssh"
export CVSROOT=":ext:dancer@prolog.local.net:/var/cvs"
    

あと,毎回パスワードを打つのが面倒な人はssh-agentの設定をしてい る事を推奨する.

CVSを適切に利用するには,GNU/Linux上で作業することが推 奨される.W○ndows版のツール類の 実装は,そこまで利用されていない ためか,あまり洗練されていない.

checkout

cvs checkout モジュール名とすると,レポジトリからモジュー ルをチェックア ウトしてくれる. チェックアウトとは, 実際にサーバにおいてあるレポジトリという直接編集のできない形式で保存 されているファイルから,自分の編集できるような形式のファイルをワーキングディレクトリとして生成す る処理である.省略するとcvs co モジュール名になる.

モジュール名は,CVSのレポジトリのディレクトリにあるディレクトリに対応する. 例えば,/var/cvsliloというディレクトリがあるのなら,それがモジュール名で ある.

チェックアウトした後の作業用のディレクトリをワーキングディレクトリと呼ぶ.

add

cvs add ファイル名とすると,現在CVSの管理下にないファイ ルをCVSの管理下に置いてくれる.これは,そのディレクトリがすでに CVSの管理下にある必要がある. -koをつけると,バイナリファイルとして扱ってくれる.そう でない場合は,サインで囲まれているもので,特定のキーワード,例 えば,Iddate等が,実際に,そのファイルのIDや, 日付等に置換される.そういうことはバイナリファイルでは起きてはな らないので,-koをつける. addをしたあとは,commitをする必要がある.

update

省略してupでも良い.通常はcvs up -dPとうつこと になる. カレントディレクトリ(ワーキングディレクトリ)以下にあるファイルに関して, CVSレポジトリから最新の物を取り入れて来て,そして, 現在自分のワーキングディレクトリにおいてある ファイルがCVSレポジトリある物から変更してあるのかという事を 報告してくれる.変更点が衝突する場合は,両方を取り入れて,ファイ ル内にConflictとして報告する.

-dPオプションをつけると,レポジトリで新しいディレクトリ を追加されたり削除されたりした時の結果が自分の作業用ディレクトリ に追加される.

なお,-D 日付オプションや,-r タグオプションで, ファイルの指定したバージョンを取り出すことができる.

大抵は,このコマンドを作業前に毎回入力することになる. そうすることによって,そのシステム上で,レポジトリ上の 最新の情報が利用できるようになる.

commit

省略して,cvs ci ファイル名でも良い.自分が変更した結果 をレポジトリに 反映させる.これをする前にupdateをしておき,コンフリクト等が起き ないようにするのがマナーである. ファイル名は、省略できる。省略した場合は、 更新されたファイルが全部commitされることになる。

通常は,cvs ci -m "message"というようにして, メッセージを指定して実行することが多い. ログを-mオプションで指定しなかった場合は, viコマンドが起動し,ログを入力するように促される. ファイル名を指定しなかった場合は,とりあえず,見付かったファイル を全部チェックインする.

remove

cvsからファイルを削除するには,まず,ファイルを削除してから, cvs remove ファイル名としてしまう.そうすると,CVSレポジ トリのattic(屋根裏部屋)に移動される(実際に削除はされない). removeをしたあとは,commitをする必要がある.

tag

現在のバージョンに象徴的な名前をつけ,後からcvs update で簡単に呼び出せるようにする.ある程度安定した時や,何か劇的な変 更を行うまえに行うのが望ましい.定期的に規則性 をもってしておくと, あとから楽である. 書式としては,cvs tag タグ名というように利用する.

init

これは管理者用のコマンドである. cvs -d /var/cvs initとすると,これからそのマシンの /var/cvsがCVSレポジトリとして利用できるようになる. その中にディレクトリを作成すると,それがcheckoutできるようになる. たとえば,cvs -d /var/cvs init とすると,mkdir /var/cvs/onetestというようにしてディレクトリを作成すると, cvs -d /var/cvs co onetestとしてレポジトリをチェックア ウトして作業用のコピー(ワーキングディレクトリ)が作成できる.

import

cvs import モジュール名 適当なタグ 適当なタグ というよ うにすると,レポジトリの指定したモジュール名のモジュールにカレン トディレクトリ以下にあるファイル全 てが取り込まれる. その後,そのモジュールをチェックアウトすると,もとあった物がCVS 管理のもとで編集できるようになる. その後,インポート元のディレクトリは必要無くなる.

その他のマイナーなコマンド

cvs annotate ファイル名とすると,誰がファイルのどの部分 を最後に変更したかという履歴が出て来る.出力例:

1.27         (dancer   22-Jun-01): add_to_list_of_candidates (int price, int memory, double hddavail, int hddspeed, const char * cpunam
e, int cpuspeed, GtkWidget* clistpointer)
1.4          (dancer   20-Jun-01): {
1.28         (dancer   22-Jun-01):   gchar * data[7];
1.8          (nagaya   20-Jun-01):   int i;
1.17         (dancer   20-Jun-01):   
1.27         (dancer   22-Jun-01):   asprintf(&data[0], "%d", price);
1.27         (dancer   22-Jun-01):   asprintf(&data[1], "%d", memory);
1.27         (dancer   22-Jun-01):   asprintf(&data[2],"%f",hddavail);
1.27         (dancer   22-Jun-01):   asprintf(&data[3],"%d",hddspeed);
1.27         (dancer   22-Jun-01):   (data[4]) = g_strdup(cpuname);
1.28         (dancer   22-Jun-01): 
1.27         (dancer   22-Jun-01):   asprintf(&data[5], "%d", cpuspeed);
1.28         (dancer   22-Jun-01):   data[6] = "";
1.21         (dancer   22-Jun-01): 
1.23         (dancer   22-Jun-01):   /*add price*/  
1.27         (dancer   22-Jun-01):   gtk_clist_append(GTK_CLIST(clistpointer),data);
1.24         (nagaya   22-Jun-01):   
1.30         (dancer   22-Jun-01):   for(i = 0; i < 6; i++)
1.26         (dancer   22-Jun-01):     {
1.27         (dancer   22-Jun-01):       free(data[i]);
1.26         (dancer   22-Jun-01):     }
1.4          (dancer   20-Jun-01): }
1.4          (dancer   20-Jun-01): 
1.3          (dancer   20-Jun-01): void
1.3          (dancer   20-Jun-01): on_window1_destroy                     (GtkObject       *object,
1.3          (dancer   20-Jun-01):                                         gpointer         user_data)
1.3          (dancer   20-Jun-01): {
1.31         (tamaki   25-Jun-01):   gtk_main_quit();  
1.31         (tamaki   25-Jun-01): }
1.31         (tamaki   25-Jun-01): 
1.33         (dancer   25-Jun-01): void 
1.33         (dancer   25-Jun-01): waitClearLine(FILE *in)
1.32         (tamaki   25-Jun-01): {
1.32         (tamaki   25-Jun-01):   char * buf = NULL;
1.32         (tamaki   25-Jun-01):   int buflen = 0;
1.32         (tamaki   25-Jun-01):   
    

cvs log ファイル名とすると,そのファイルのいままでの履 歴が分かる.出力例:

revision 1.42
date: 2001/06/26 06:51:26;  author: dancer;  state: Exp;  lines: +5 -6
updates
----------------------------
revision 1.41
date: 2001/06/26 06:39:41;  author: dancer;  state: Exp;  lines: +4 -3
indent
----------------------------
revision 1.40
date: 2001/06/26 06:33:11;  author: dancer;  state: Exp;  lines: +10 -11
removed bufsize, and fixed regexp in fscanf.
----------------------------
revision 1.39
date: 2001/06/26 06:20:26;  author: tamaki;  state: Exp;  lines: +39 -2
*** empty log message ***
----------------------------
revision 1.38
date: 2001/06/26 04:41:47;  author: dancer;  state: Exp;  lines: +13 -7
added a dialog box
----------------------------
    

cvs diff ファイル名とするとワーキングディレクトリにあるファイルと, レポジトリの状態との差分を表示してくれる.

心得

できるだけ,こまめにupdate,commitをする事が望ましい.急に大きな 変更をされると,迷惑である. そういう事をすると,コンフリクト(衝突)が起きる確率が増える. コンフリクトの処理は面倒である. そういう事をするのなら,ブランチを作 成しておいてそこで作業し,完成したら,基幹にマージすると良い.

EMACS

EMACSにはpcl-cvsモードとVCモードがあり,その二つを併用して 作業する.

VCモード

VCモードはファイル単位で利用する場合に重宝する. ファイルを編集している時にC-x v vと押すと,現在のファイルに対して 最も一般的に実施するだろうと思われる事が起きる.

状況 実施内容
新しいファイルである CVSレポジトリに新規登録する
CVSレポジトリの内容が変更されている CVSレポジトリの内容の変更されたぶんを自分のソースにマー ジする
ワーキングディレクトリの内容がCVSレポジトリの内容から変更され ている 変更点をコミットする

実際に使ってみると,C-x v v はかなり打ちにくいので, .emacs(global-set-key "\C-x\C-v" 'vc-next-action) などの設定をしておき,もっと打ちやすいキーに変更しておくのが望ま しい.

pcl-cvsモード

Emacsにはpcl-cvsモードという,ワーキングディレクトリを一まとめとして 管理するためのモードがある.なれると使いやすい.

M-x cvs-updateでCVSアップデートバッファになる.そこで以 下のコマンドが利用できる.

キー 意味
g 再度cvs update を行う
m ファイルにマークをつける
c Mがついているファイルの変更をCVSレポジトリに反 映(commit)する
i .cvsignoreというファイルに追加して,cvsの管理から外す
a ?がついているファイルをCVSの管理に登録

他のCVSツール

TkCVS

tcl/tkのCVSインタフェースもある.見ためは良い感じである.マウス の操作が好きな人はどうぞ. TkCVS screenshot

LinCVS

LinCVS screenshot

Cervisia

Cervisia screenshot Cervisia diff screenshot

gcvs

gcvs

WinCVS

熱烈なWindows ユーザのために,WinCVS等のソフトがある.とりあえずだれかが書い ている文書.

WinCVSは,zipファイルを取得後,その中の setup.exeを実行して質問に適当に答える.そうすると,スタートメニュー のGNUの右ににあるwincvsという所に wincvsが現れるので,それを実行する.設定させられるので,適当に設 定.そして,サーバがどこにあるのかという設定をして,loginして, チェックアウトする.

その後は自分のところにあるファイルを編集し,commit等をすれ ばよい.commitとupdateをすると,ファイルの変更点がサーバにあるレ ポジトリとの間で交換される. これで,共同作業を円滑に行う事ができる.これでもう, ftpやWindowsの shareを利用することなく,作業の分担等ができるようになる.

ただ、現在一番信頼性が良い Windows上のCVSアプリケーションは、 cygwinのCVSであるようだ。

CVSの管理者は?

レポジトリを作成する時には,まずCVSUSERみたいなグループを作成し, それにchownしておく.あと,アクセス権限は,グループが書き込める ようにしておく.モジュールの作成は,mkdirして,chown してグルー プをメンバが編集できるように作ったグループに変更,そしてchmodし てグループ権限,そして+sしておくとさらに良い.

日常としては,ユーザの追加する時は, ユーザを作成,それを全CVSユーザの入っているグループに追加 (CVSROOTいじれる権限を与える),あと,CVSのユーザはおそらく複数の ひとに限られるプロジェクトを行うので,そのユーザをそのグループに 追加.これでセキュリティー的には,内部の人しか使わないのなら,良 いのだろうと思われる.

winCVSのユーザがいる場合には,pserverを設定しておいた方が親切で あるのかもしれない.ただ,pserverはCVSの独自プロトコルで,過去の履歴からみると, 脆弱性がしばしば発見されており,必要でないなら利用しないのが望ましい. 近頃であれば,sshはほとんどの人が利用できるだろうから,そちらの方が良いだろう. CVSを利用しようとする場合, Windowsはそのままでは非常に貧弱なシステムである. まともに利用しようとするなら, Cygwinをインストールすることが必要だ. 経験上,CygwinのCVSをそのまま利用する事を推奨する.

commitinfoというファイルは,コミットをするべきかどうか を確認してくれるようなスクリプトである.これを有効に利用すると, 不適切な文字コードのデータなどをはじく事ができると思われる.

ウェブページの管理を行う場合には,CVS管理で,実際に見れるファイルと 言う物も生成する必要がある.その方法としては,簡単な物として,例 えば,/home/dancer/public_htmlにモジュールをチェックア ウトしてしまうということが考えられる.そこは直接は変更しないで, cron等で自動的にcvs updateを行う.


Junichi Uekawa

$Id: cvs.html.ja,v 1.29 2005/08/06 05:45:01 dancer Exp $