UNIX/Linuxの部屋 CVSトピック編コマンドの使い方

TOP UNIX/Linuxの部屋 UNIX/Linuxコマンド一覧 用語集 新版 由来/読み方辞書 環境変数マニュアル Cシェル変数 システム設定ファイル システムコール・ライブラリ ネットワークプログラミングの基礎知識 クラウドサービス徹底比較・徹底解説




コマンド CVSトピック編 CVS に関するいろいろな情報 このエントリーをはてなブックマークに追加

本項は、CVS の使用方法をひととおりマスターした人向けの説明である。CVS の使い方そのものがわからない場合は、まずチュートリアルをどうぞ。

CVS のマニュアルでは init・checkout などをコマンドと命名しているが、ここではあえてサブコマンドと表記する。

リビジョン番号
リビジョン番号は 1.1 からスタートして、1.2・1.3・1.4 … 1.99・1.100・1.101 … と上がっていく。たまに
「メジャーバージョンが上がったら 2.0 にしたい」
と言う人がいるが、これはやめた方がよい。普通は 1.xx のままにしておいて、このような管理はタグで行う。タグであれば後から削除することもできるが、リビジョンを 2.0 にあげてしまえばもう元に戻すことができない。例えば「リリース直前に障害多発のためリリースは延期」となってももうリビジョンは元に戻せない。

さらに言えば、リビジョンはただのファイルごとの通番である。一方、メジャーバージョンというのは、そのファイルが社会の中でどのような位置づけにあるか (正式版なのか、テスト版なのか) という概念である。まわりの状況が変われば、この位置づけも容易に変わるものである (先にあげたリリース延期など)。このようなあやふやな概念を、通番とリンクさせるのは得策ではない。タグという緩いつながりで結ぶことで、変化に柔軟に対応しやすくしておくわけである。ちなみに当ページ管理人は、有名なオープンソースのプロジェクトで 2.x とか 3.x などとリビジョンを上げているものを見たことがない。

どうしてもやりたければ、コミットの際に
% cvs commit -r 2.0
とすることで実現できるが、ファイルが修正されていない場合はコミットできないため (プロジェクト全体のメジャーバージョンは上がっても、全ファイルに修正が入るとは限らない)、$Id を修正したり、適当な場所に空白を入れたりして無理矢理コミットすることになる 。その結果、実質的にはファイル内容に変化がないのに、リビジョン 2.0・3.0・4.0 ができてしまう、ということになる。

さらに、
「メジャーバージョン.マイナーバージョン.バグFIXバージョン.メッセージ等修正バージョンとしたい」
などという人がいるが、これもやめた方がよい。というより、CVS ではたぶんできないような気がする (リビジョン番号はブランチ管理も兼ねているため)。

状態一覧
cvs status で表示される状態の一覧を以下に示す。
Up-to-date 最新版。リポジトリの最新リビジョンと内容が完全に一致している状態
Locally Modified 作業場所のファイルを修正したが、まだコミットしていない状態
Locally Added ファイルを cvs add したが、まだコミットしていない状態
Locally Removed ファイルを cvs remove したが、まだコミットしていない状態
Needs Checkout 自分以外の誰かが新たなファイルを追加したが、手元の作業場所ではまた cvs update していない状態。あるいはチェックアウトしたファイルを rm で消した状態。
Needs Patch 自分以外の誰かがコミットしたものの、手元の作業場所は cvs update していないため、手元のファイルが古い状態
Needs Merge
Unresolved Conflict 複数人が名前が同じファイルを cvs add して片方がコミットした場合、もう片方ではこの状態になる。誰がどのファイルを追加するかの認識にずれがある。コミュニケーションを密にとろう。
File had conflicts on merge CVS によるマージの際に、衝突 (コンフリクト) が発生した。ファイルの衝突部分を修正してコミットすればよい。
Unknown 不明なファイル。cvs status [存在しないファイル] などとした状態
Entry Invalid 誰かが作業場所で cvs remove してコミットを行った後に、別の作業場所で同じファイルを rm で削除した、など

複数アカウントでの利用
ひとつのアカウントで CVS を利用している場合は何ら問題ないが、複数のアカウントで CVS を利用する場合は、リポジトリの所有者とパーミッションが問題となる。

リポジトリがローカルに置いてあるとき、CVS を操作するということは結局はリポジトリのファイルを読み込んだり、変更したりしているわけである。もし userA と userB という 2つのアカウントから操作をする場合は、いずれのアカウントからもリポジトリのファイルに対して read・write 権限を与えなければならない。

当ページ管理人がよくやる方法は以下の通りである。まず、cvs というグループを作成し、そこにリポジトリにアクセスできるアカウントを追加する。例えば /etc/group に
cvs:*:3000:userA,userB
と記述する。追加後は id コマンドを実行して、cvs グループに加わっていることを確認しよう。
% id
uid=1001(userA) gid=101(userA) groups=0(wheel), 3000(cvs)
そしてリポジトリのグループを cvs に変更し、グループに対する write 権限を与える。
(ここでの $CVSROOT は CVS リポジトリの場所を表す)
% chgrp -R cvs $CVSROOT
% chmod -R g+w $CVSROOT
これで userA と userB の両方が、全ファイルを修正できるようになった。さらに Solaris などの SystemV 系 UNIX では、ディレクトリに対して setgid ビットを立てておく。
% find $CVSROOT -type d | xargs chmod g+s
その理由は chmod の setgid の項を参照してほしい。

rsh・ssh・pserver
未稿。

日時
CVS では日時を UTC (いわゆるグリニッジ標準時) で管理している。cvs log や cvs status で表示される日時は UTC である。ところが cvs checkout・cvs diff・cvs update などのサブコマンドオプション -D は、ローカルタイムとして扱われる。

以下、タイムゾーンが JST であると仮定する。
% date
Sun Jul 31 02:57:08 JST 2005
⇒ date コマンドでタイムゾーンが JST となっている
cvs log の結果が以下のようになっていたとする。
% cvs log file.txt
----------------------------
revision 1.3
date: 2005/07/30 10:00:00; author: 68user; state: Exp; lines: +1 -0
修正その 2
----------------------------
revision 1.2
date: 2005/07/30 05:00:00; author: 68user; state: Exp; lines: +1 -1
修正その 1
----------------------------
revision 1.1
date: 2005/07/30 00:00:00; author: 68user; state: Exp; lines: +1 -1
初期バージョン
このときリビジョン 1.3 のコミット時刻は「2005/07/30 10:00:00」となっている。しかしリビジョン 1.3 と比較するつもりで
% cvs diff -D "2005/07/30 10:00:00" file.txt
と -D オプションで日時を指定した場合は JST として解釈されてしまい、UTC の 2005/07/30 01:00:00 として扱われる。その結果、リビジョン 1.3 ではなく、リビジョン 1.1 と比較することになってしまう。

CVS の出力は UTC だが、ユーザの入力はローカルタイムとして扱われるというわかりにくい仕様で、なおかつ JST や UTC などのタイムゾーンが一切表示されないため、勘違いしやすい。これは CVS のひどい欠陥である。当ページ管理人の結論としては「日時に頼るな、タグを使え」である。

なお、日時表記を JST などに統一する方法は存在しない (少なくとも cvs-1.11.5 では)。「タイムゾーンをまたがる開発をする場合は UTC じゃないと困る」と言う人もいるが、当ページ管理人がこれまで CVS を利用した環境は、全て JST であった。ちなみに cvsweb では設定ファイルにてタイムゾーンを設定できて便利である。

エンコーディングの統一
ファイルとコミットログのエンコーディング (文字コード) は統一しておこう。もしファイルが Shift_JIS・コミットログが EUC-JP などとエンコーディングが混在していた場合は、CVS 的には何ら問題はないが、扱う人間にとっては管理しづらくなる。

当ページでは全てファイルのエンコーディングは EUC-JP にしている。また、コミット時に起動するエディタ (emacs) のエンコーディングも EUC-JP としているため、コミットログも EUC-JP となる。

サブコマンドの別名
CVS はサブコマンドが長いので、いちいち cvs checktout や cvs update とタイプするのは結構ダルい。そういう人のために短めの別名が定義されている。
サブコマンド 別名 (短縮系)
add ad または new
admin adm または rcs
annotate ann または blame
checkout co または get
commit ci または com
diff di または dif
export exp または ex
history hi または his
import im または imp
log lo
login logon または lgn
rannotate rann または ra
rdiff patch または pa
release re または rel
remove rm または delete
rlog rl
rtag rt または rfreeze
status st または stat
tag ta または freeze
update up または upd
version ve または ver
別名の数は多いが、当ページ管理人が使うのは cvs co・cvs up・cvs di くらいである。この一覧は cvs --help-synonyms で確認できる。これでも我慢できない人は、tcsh の complete コマンドでがんばって補完の定義をしよう。

ヘルプ
全体のオプションを表示
% cvs --help
共通オプション一覧を表示
% cvs --help-options
サブコマンド一覧を表示
% cvs --help-commands
サブコマンドの短縮形一覧を表示
% cvs --help-synonyms
サブコマンドの書式 (サブコマンドオプションとサブコマンド引数) を表示
% cvs [サブコマンド] --help

ヘルプオプション自体にも短縮形があり、上記のヘルプはそれぞれ
% cvs --h
% cvs --help-o
% cvs --help-c
% cvs --help-s
% cvs [サブコマンド] -h
としてもよい。

キーワード置換
未稿。

バイナリファイル
CVS はバイナリファイルの扱いがちょっと苦手である。なぜなら、バイナリファイル中にたまたま $Id や $Log などのキーワードが入っていた場合、キーワード置換が行われるからである。ほとんどの画像ファイルなどは、$Id と同じコードが含まれていることはまずないので、よほど運が悪くなければ本当にキーワード置換が行われることはない。

しかし念のため「このファイルはバイナリファイルなのでキーワード置換はしないこと」というマークを付けておこう。cvs add の際に -kb オプションを付けることでバイナリファイルのマークが付けられる。
% cvs add -kb newimage.jpg
このマークは、cvs status で確認できる。
% cvs status newimage.jpg
File: newimage.jpg      Status: Up-to-date

   Working revision:    1.1     Sun Jul 31 09:01:31 2005
      Repository revision: 1.1     /home/68user/cvsroot/hello/newimage.jpg,v
      Sticky Tag:          (none)
      Sticky Date:         (none)
      Sticky Options:      -kb (★ここ)
cvs add 時に -kb を付け忘れてコミットしてしまった場合は、後から cvs admin で -kb を追加できる。
% cvs admin -kb newimage.png
RCS file: /home/68user/cvsroot/hello/newimage.png,v
done
admin -kb で修正されるのはリポジトリ側だけなので、手元のファイルはまだキーワード置換が行われたファイルである (もしキーワードが含まれていれば)。ステータスが「Needs Checkout」になるので、
% cvs update newimage.png
としてキーワード置換を抑止したファイルを取得しなおすこと。キーワード置換は、コミット時に行われるのではなく、ファイル取得時 (checkout・update) に行われるので、これで正しいファイルを取得できる。

とはいえ、ファイルを追加する際に -kb を付けるのではいつかミスが起きそうである。そこで CVSROOT/cvswrappers に「この拡張子はバイナリファイル」と記述しておけば、勝手にバイナリファイルとしてキーワード置換が抑止される。
% cd work (適当な作業場所に移動)
% cvs checkout CVSROOT
cvs checkout: Updating CVSROOT
U CVSROOT/checkoutlist
U CVSROOT/commitinfo
U CVSROOT/config
U CVSROOT/cvswrappers
U CVSROOT/editinfo
U CVSROOT/loginfo
U CVSROOT/modules
U CVSROOT/notify
U CVSROOT/rcsinfo
U CVSROOT/taginfo
U CVSROOT/verifymsg
% cd CVSROOT
として、cvswrappers に以下の行を追加する。
*.gif -k 'b'
*.jpg -k 'b'
*.png -k 'b'
最後にコミットを忘れずに。
% cvs commit -m '*.{gif,jpg,png} はキーワード置換を抑止' cvswrappers

リポジトリのコピー
未稿 (repocoy した後はタグを外すのを忘れずに)。

リポジトリの移動
未稿。

ファイルを古いバージョンに戻す
未稿 (ロールバック的なことはできない。古いファイルを持ってきてコミットすること)。

CVS の補助ツールたち
cvsweb
cvsweb は、web 上から CVS リポジトリを閲覧するツール (CGI プログラム) である。あくまで閲覧ができるだけで、web 上からコミットなどの操作は行えない。cvsweb にはいろいろなバージョンがあるが、当ページ管理人は以下のように認識している。
  • Fenner 氏が最初に cvsweb を開発した
  • Zella 氏が改良した (annotate 機能・色付き diff など)
  • knu 氏が Zella 氏に機能改善のパッチを送ったが全く採用してくれないので、fork して knu-cvsweb を作った
  • その結果、Zella-cvsweb と knu-cvsweb が並行して開発されていた
  • knu-cvsweb は FreeBSD-cvsweb に名称変更 (FreeBSD-cvsweb 2.0 からスタート)
  • Zella-cvsweb は実質的に開発停止
  • 現在は knu 氏は FreeBSD-cvsweb から手を引き、FreeBSD CVSWeb Project が開発を続けている。FreeBSD-cvsweb 3.0 あたりが最新版

当ページで使用している cvsweb
は knu-cvsweb-1.105.1.65 である (knu-cvsweb の 1.65 で、fork 時点から Zella-cvsweb-1.105 までの機能をとり入れたもの)。

cvsweb.cgi と cvsweb.conf を置いて適当に修正すれば動く。当ページ管理人が修正した部分は以下のとおり (メッセージの日本語化も含む)。
修正理由も書いたので、適当に拾っていってほしい。
なお、cvsweb はローカルにリポジトリがないと動作しない (rsh・ssh・pserver 経由ではアクセスできない)。リポジトリと同じマシンで cvsweb を動かすか、定期的にリポジトリをコピーする仕組みを作ること。

ちなみに同種の web インタフェースとして ViewCVS というのもある。cvsweb との機能的な差違はほとんどないと思われるが、cvsweb は Perl で、ViewCVS は Python で記述されているところが大きな違いだろうか。

cvsgraph
web 上でリポジトリの分岐状況などをグラフ表示するツール。ブランチを導入していないならあまり意味がない。また、開発期間が長くなると画像が大きくなりすぎていまいち見づらい。
perl スクリプトなので、GD モジュールを適当にインストールすれば動く。cvsweb からリンクを張りたい場合は、FreeBSD-cvsweb 3.0 あたりなら cvsweb.conf の設定変更で OK。

SandWeb
cvsweb や ViewCVS はリポジトリを閲覧するだけだが、SandWeb は web 上から cvs のすべての操作を行うことができる。ただし、使いものになるかどうかは知らない (使ったことがない)。SandWeb は Cvswebclient の後継プロジェクトのようだ。