■第4章 CVSの少し賢い使い方【クライアント編】 ■■4.1 個人環境を整えよう さて、基本的なコマンドの使い方に慣れたところで、ちょっと個人環境を整えて暮らしやすくしておきましょう。個人環境の設定には、環境変数と個人環境の設定ファイルを使用します。全体の設定をおこなうには、管理ファイルを用います。管理ファイルの設定方法は、5章で説明します。 ■■■4.1.1 環境変数を設定しよう リポジトリの初期化のところで、CVSROOTという環境変数を設定するという話をちょっとだけしました。この他にCVSが参考にする環境変数には、CVSREAD、RCSBIN、CVSEDITOR、CVS_IGNORE_REMOTE_ROOT、CVS_RSH、CVS_SERVER、CVSWRAPPERSという7つがあります。このうち、RCSBINは1.9以前のバージョンでしか使いません。そして、今の段階で設定して嬉しいのは、CVSEDITORだけです。CVS_RSHは、遠隔にあるCVSサーバを利用するときには、設定する必要が出てきます。これについては5章で説明します。ここでは、CVSEDITORの設定をしようと思います。 ■■■■CVSEDITORって何のための環境変数? 前節でimport、add、commitというコマンドに、-mというオプションをつけていたことを覚えていますか? -mはファイルの変更履歴の中にログメッセージとして埋め込まれる文字列を指定するためのオプションでした。このオプション、省略するとどうなるでしょう。やってみましたか? importとcommitの場合には、「ログを入力しろ〜」と言わんばかりに何かエディタが立ち上がってくるはずです。ちなみに、addは立ち上がってきません。何故かは私はよく分かりません。CVS設計者がそう判断したんでしょうが、誰か知っていたら教えてください。 ■■■■いきなりエディタが立ち上がってきたらどうしたらよいの? UNIXがよく分からない人はびっくりしたかもしれませんね。多分viというエディタが立ち上がってくると思いますので、そのときは、:q!と続けて入力して終ってください。viの操作を知っている人は、何かログメッセージをつけてから終了しても構いません。ログメッセージをつけた場合にはそのまま、処理は続行されますし、ログメッセージをつけなかった場合には、どうするのかCVSが聞いてきます【図4.1】。 【図4.1】ログメッセージをつけなかったとき(commitの場合) ▼ Log message unchanged or not specified a)bort, c)ontinue, e)dit, !)reuse this message unchanged for remaining dirs Action: (continue) ▲ 一番最初のメッセージは、「ログメッセージが変わっていないか、入力されてないよ」という意味で、次にユーザにどうするかきいて聞いてきます。ここで、ユーザはa、c、e、!の4文字から1文字を入力して動作を選択できます。aはabortつまり、処理(ここではcommitの処理)そのものをやめてしまいます。cはcontinueつまり、処理を続行します。eはeditつまり、もう一度エディタを起動してログメッセージ入力可能状態にします。!も処理を続行しますが、対象の中にディレクトリが含まれる場合の動作が、continueと異なります。continueは同じディレクトリに含まれるファイルには同じログメッセージ(ここではログメッセージ無し)を適用しますが、次のディレクトリに移るとまたエディタを起動し、ログメッセージ入力を促します。一方、!は残ったディレクトリに含まれるファイル全てに対して、同じログメッセージを適用し終ります。 ログメッセージの入力ができなかった人は、aで中断し、-mオプションでログメッセージを指定しなおすか、次で説明するようにエディタを指定してログメッセージを入力してください。もちろん、ログメッセージをつけたくなければ、cなり!で続行しても構いません。 ■■■■立ち上げるエディタを変えられないの? 変えられます。viだと日本語が書けませんし他のエディタの方が使いなれているかもしれませんから、何か他のエディタを指定できると便利ですよね。もちろん、vi使いかつ英語でがんばってもらっても構いません。ソフトウェアのソースコードを世界中の開発者とCVSで共有するような場合には、ログも英語で書くのは当然ですが、そういう場合は少ないとは思います。 CVSは、どのエディタを立ち上げるか次の順で判断します。まず、全体にかかるオプションである-eでエディタが指定されていれば、それを起動します【図4.2】。-eオプションが指定されてなければ、環境変数CVSEDITORがセットされているかチェックします。CVSEDITORがセットされていれば、そのセットされたエディタを立ち上げようとします。CVSEDITORがセットされていない場合には、環境変数EDITORをチェックします。それもセットされていないようであれば、UNIXなら大抵入っているエディタviを起動しようとします。 【図4.2】オプション-eをつけてcommit ▼ cvs -e emacs commit ▲ 環境変数はセットしたくない、とか、環境変数EDITORや、CVSEDITORにemacsを指定しているが、都合によりviが使いたいなどというときには、-eで指定するようにするとよいでしょう。 ■■■■CVSEDITORはどうやってに設定すればいいの? 環境変数CVSEDITORの設定法は、CVSROOTと同じようにします。たとえば、設定したいエディタをemacsとすると、シェルの系統によって次のように環境変数を設定します。 CSH系のシェルを利用している場合 setenv CVSEDITOR emacs SH系のシェルを利用している場合 CVSEDITOR=emacs; export CVSEDITOR commitコマンドを-mをつけないで実行してみてください。指定したエディタが起動してきましたか? ちなみに、環境変数にセットしたエディタがパスが違っているなど何らかの理由で起動できない場合には、思いっきり文句を言われます【図4.3】。 【図4.3】エディタの起動に失敗(commitの場合) ▼ cvs commit: cannot exec /usr/ucb/vi: No such file or directory cvs commit: warning: editor session failed Log message unchanged or not specified a)bort, c)ontinue, e)dit, !)reuse this message unchanged for remaining dirs Action: (continue) a ▲ この動作は、上でエディタで編集をおこなわないで終った時と同じですね。上での説明を参考に、aでやめるか、もしくはcまたは!で空のログメッセージを適用するか判断してください。 ■■■4.1.2 個人環境設定ファイルを設定しよう CVSの実行環境を個人毎に設定する設定ファイルには、.cvsrc、.cvswrapper、.cvsignoreの3つがあります。 ■■■■.cvsrcファイル UNIXでCVSを使用している人は、.cvsrcというファイルでコマンドにいつも付けるオプションを指定しておくことができます。これは、一般的な初期化ファイルと同様にホームディレクトリ(~/)に置きます。たとえば、前の節で説明したように、updateにいつもオプション-dと-Pをつけたければ、update -d -Pと書きます。また、releaseには-dをつけたいとすると、次の行にrelease -dと書くようにします。 【図4.4】.cvsrcの例 ▼ update -d -P release -d ▲ 何らかの理由で.cvsrcの設定をコマンド実行時に無効にしたい場合には、cvs -f update ...のように-fオプションを指定します。なんで、-fなのかは知りません(なんでだろ)。上で設定した状態で、-fなしでの実行と-fを指定して実行した場合のreleaseコマンドの挙動の違いを見てみましょう。【図4.5】の3行目の出力が、-dオプションつきで実行した場合の(and delete)が含まれたメッセージであったのが、【図4.6】の3行目では-dオプションがつかない場合のメッセージに変わっているのがわかると思います。 【図4.5】-fなしで実行した場合 ▼ cvs release cvstest You have [0] altered files in this repository. Are you sure you want to release (and delete) directory `cvstest': n ** `release' aborted by user choice. ▲ 【図4.6】-fつきで実行した場合 ▼ cvs -f release cvstest You have [0] altered files in this repository. Are you sure you want to release directory `cvstest': n ** `release' aborted by user choice. ▲ ■■■■.cvsignoreファイル .cvsignoreという名前のファイルをホームディレクトリ直下に作成しておくと、その中に記述されたファイルは、updateコマンド実行時にカレントディレクトリなどいくつかのファイルをまとめて対象とした時に、CVSがチェック対象から外すようになります。 たとえば、TeXなどを使用している場合、texファイルをコンパイルすると、.aux、.dvi、.logというサフィックスのついたファイルが生成されます。こういうのがたくさん出てくるようになると、updateコマンドを実行すると一覧にずらずらと並ぶようになります。そうすると、これら作業上は意味のないファイルに埋もれて、他のファイルが見えにくくなってしまいます。このような場合に、特定のファイルを無視するようにするのが、.cvsignoreファイルの役割です。 【図4.7】色々ファイルを用意してみて、update ▼ % ls -F CVS/ newdir2/ test.c test.log test.tex test2.txt~ dir1/ test.aux test.dvi test.o test2.txt tmp2.txt % cvs update cvs update: Updating . ? test.tex ? test.c ? test.aux ? test.dvi ? test.log cvs update: Updating dir1 cvs update: Updating dir1/dir2 cvs update: Updating newdir cvs update: Updating newdir2 ▲ なお、Cのソースコードをコンパイルすると生成される.oファイル、およびemacsのバックアップファイルである最後に~(チルダ)がついたファイルは、CVSでは始めからチェックしないようです。では、.aux、.dvi、.logファイルを無視するような.cvsignoreを書いてみましょう【図4.8】。 【図4.8】.aux、.dvi、.logを無視するための.cvsignoreファイル ▼ *.aux *.dvi *.log ▲ test.auxでもhoge.auxでもマッチするようにワイルドカード*を使用してパターン*.auxというように指定しています。*.dvi、*.logも同様です。なお、ファイルのパターンの区切りは空白でなく改行でも構いません。読みやすさを優先するなら一行ずつに書いた方がよいでしょう。これを、~/.cvsignoreとして置いて、cvs updateを実行すると【図4.9】のようになります。さっぱりしましたね。 【図4.9】.aux、.dvi、.logは無視されたかな? ▼ % cvs update cvs update: Updating . ? test.tex ? test.c cvs update: Updating dir1 cvs update: Updating dir1/dir2 cvs update: Updating newdir cvs update: Updating newdir2 ▲ なお、管理ファイルの中にもcvsignoreというファイルがあります。中の書き方と、そこに書かれたファイルを無視するようになるのも同じです。違うのは、その影響がその個人環境下ではなくそのリポジトリを使用している全ての環境(他の人も含む)に影響することです。また、作業コピーの各ディレクトリ下にも同名の.cvsignoreを置くことができ、こちらも記述法・機能は同じですが、影響がそのディレクトリのみと狭くなっています。サブディレクトリには影響しません。無視したい対象ファイルがどの程度一般的か、その影響領域を考え合わせてどのファイルに設定するか考えてください。 ■■■■.cvswrapperファイル .cvswrapperというのは、CVSの入出力時のフィルタリング機能で、動作を指定するためのファイルです。具体的には、条件にマッチしたファイルがリポジトリから取り出されたり、戻されたりするときに、指定されたフィルタをそのファイルに対してかけるということをします。あるファイルに対して、フィルタをかけるというのは、要するに、なんらかの変換をするプログラムをそのファイルに対して実行する、という意味です。管理ファイルの中にも同じ役割をするcvswrappersというファイルがあります。書式も同じです。 現在この機能は使用を推奨されていません。そのうち無くなってしまうという話です。しかし漢字コード変換にはこの機能を使用しているので、Windowsマシン上のCVSクライアントとUNIXマシン上のCVSクライアントで、UNIXサーバ上のデータを共有して作業している人はこの設定が必要になることがあります。この設定方法については、第5章で説明します。 ■■4.2 もう少し便利なコマンドの使い方 3章では、addやcommitなど必須のコマンドについて説明しましたが、CVSには知っていると便利なコマンドがもっともっと沢山あります。ここでは、特にバージョン(リビジョン)情報を活用する方法など、共同作業しない場合でも有用なコマンドについて説明します。 ■■■4.2.1 タグをつけてみよう CVSの管理しているバージョン情報を活用するためには、ある時点のモジュールにタグという名札のようなものをつけたり外したりして取り出しやすくするのと便利です。 ■■■■タグって何? タグ(tag)と聞くと、映画「プライベート ライアン」に出て来た「dog tag」という単語を思い出します。日本語訳は認識票ということです。値札もtagですね。CVSでタグをつけるというのは、ある時点のモジュールに含まれるファイル群に識別札としてのマークをつけるということです。一旦このようなタグをつけておけば、checkoutやupdateの-rオプションにそのタグを指定することでその時点の作業コピーを取り出すことできます。 イメージ図を【図4.10】に示します。【図4.10】で中央に3本走っている矢印つきの線がa.txt、b.txt、c.txtという3つのファイルの過ごしてきた時間だと考えてください。途中にある四角がコミットされた時点で、中の番号がそのとき割り当てられたリビジョンだとします。ある時点でTAG1とつけたとし、そのあとTAG2とつけたとします。この状態で、checkoutやupdateでTAG1を指定すると、それぞれ1.2、1.10、1.6というリビジョンのファイルを取り出すことができます。同様に、TAG2というタグを指定すると、それぞれ1.3、1.12、1.6というリビジョンのファイルが取り出せるわけです。c.txtの1.6のリビジョンのように、ひとつのリビジョンに複数のタグがついても構いません。 【図4.10】タグづけのイメージ図 tag.gif ■■■■ある時点のモジュールにタグをつけるには tagコマンドもしくはrtagコマンドを使用します。tagコマンドおよびrtagコマンドの書式は、それぞれ【図4.11a】、【図4.11b】のようになります。 【図4.11a】tagコマンドの書式 ▼ cvs tag [-flRF] [-b] [-d] [-c] [-r リビジョン|-D 日付] タグ [ファイル群...] ▲ 【図4.11b】rtagコマンドの書式 ▼ cvs rtag [-aflRnF] [-b] [-d] [-r リビジョン|-D 日付] タグ モジュール群... ▲ tagには作業コピーが必要なのに対して、rtagには作業コピーが必要ありません。加えて、rtagにはある、-aオプション(削除されたファイルからタグを除去する)と-nオプション(modulesで指定されたプログラムを実行しない:6.3.6を参照)がtagコマンドにはありません。作業ディレクトリがない場合や、rtagコマンド固有のオプションを使用したい場合にrtagを使うのがよいでしょう。rtagを使用する場合には、CVSROOTか-dオプションでリポジトリを指定します。作業コピー内では指定しなければ、CVS/Rootのリポジトリを見にいきますが、相対パスは使えません。 ■■■■タグをつけてみよう cvstestというモジュールの中のtagtest.txtというファイルにタグをつけてみます。【図4.12】がtagコマンドを使った場合、【図4.13】がrtagコマンドを使った場合です。【図4.12】では、tagtest.txtが置いてある作業コピー内ディレクトリにいるとします。途中ちょっと編集してバージョンを1.1から1.2に進めたとしましょう。 【図4.12】tagコマンドでタグをつけてみる ▼ % cvs tag "TAGTEST1" tagtest.txt T tagtest.txt ▲ 【図4.13】rtagコマンドでタグをつけてみる ▼ % cvs -d /home/cvsroot rtag "TAGTEST2" cvstest/tagtest.txt ▲ tagコマンドでは、ファイル名にTというマークが先頭についたメッセージが返ってきましたが、rtagでは何のメッセージも返ってきませんでした。ちょっと不安になりますね。ファイルにタグがついているかどうかは、statusコマンドをオプション-vをつけて実行することで見ることができます【図4.14】。 【図4.14】ファイルにタグがついてるかどうか見てみる ▼ % cvs status -v tagtest.txt =================================================================== File: tagtest.txt Status: Up-to-date Working revision: 1.3 Thu Jan 25 22:53:07 2001 Repository revision: 1.3 /home/cvsroot/cvstest/tagtest.txt,v Sticky Tag: (none) Sticky Date: (none) Sticky Options: (none) Existing Tags: TAGTEST2 (revision: 1.2) TAGTEST1 (revision: 1.1) ▲ Existing Tagsの下に並んでいるのが、タグとその対応するリビジョンです。つまり、この例では、リビジョン1.1にTAGTEST1がリビジョン1.2にTAGTEST2というタグがついていると表示されています。これは、さっきの指定と同じです。間違いなくタグがついています。 ■■■■タグを消してみよう タグをつけ間違えることもありますし、あるタグを使わなくなって邪魔になることもあります。そういうときはタグを消したくなるでしょう。タグを消すにはtagまたはrtagコマンドの-dオプションを使います。つまり、【図4.15】のように、tagコマンドに-dオプションと消したいタグを指定して実行します。と、先頭にDのついた出力があり、statusコマンドを使えばタグが消えていることが確認できます。確かにExisting Tagsの中からTAGTEST2は消えていますね。 【図4.15】tagコマンドでタグを消してみる ▼ % cvs tag -d "TAGTEST2" tagtest.txt D tagtest.txt % cvs status -v tagtest.txt =================================================================== File: tagtest.txt Status: Up-to-date Working revision: 1.3 Thu Jan 25 22:53:07 2001 Repository revision: 1.3 /home/cvsroot/cvstest/tagtest.txt,v Sticky Tag: (none) Sticky Date: (none) Sticky Options: (none) Existing Tags: TAGTEST1 (revision: 1.1) ▲ もちろん、rtagコマンドでも消すことができます。作業コピー内だと、リポジトリを指定する必要はなかったりしますが、モジュールのはじめからファイルを指定する必要があります。つまり、tagtest.txtとだけ指定することはできなくて、cvstest/tagtest.txtと指定しなくてはいけません【図4.16】。 【図4.16】rtagコマンドでタグを消してみる ▼ % cvs rtag -d "TAGTEST2" cvstest/tagtest.txt D tagtest.txt % cvs status -v tagtest.txt =================================================================== File: tagtest.txt Status: Up-to-date Working revision: 1.3 Thu Jan 25 22:53:23 2001 Repository revision: 1.3 /home/cvsroot/cvstest/tagtest.txt,v Sticky Tag: (none) Sticky Date: (none) Sticky Options: (none) Existing Tags: No Tags Exist ▲ ということで、Existing Tags:領域からタグ名がなくなり、「タグはないよ(No Tag Exist)」というメッセージになりました。 ■■■■つけられないタグ名があるの? あります。non-visible characterつまり空白やタブなどの見えない文字をつけることはできませんし、エスケープ・シークエンスが入っている日本語などは使えません。?や\などは使えますが、「$,.:;@」の5文字は使えません。試しに「abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\!#%^&*()-=\`_+|~[]{}'/<>?"」というタグをつけてみましたが通りました。rcs.cをざっと見た感じでは、文字数制限は特にないようです。そんなに長いタグをつけるのも大変だと思いますが、分岐(ブランチ)を使う場合には結構長いタグをつけることもあるようです。 ■■■■Stickyタグって何? 著者ははじめて-rオプション(-Dもなんですが)を指定してファイルをアップデートしたとき、困ったことに遭遇しました。そのファイルを編集して、いざコミットするという段になってコミットできなかったのです。ちょっと、やってみましょう【図4.17】。 【図4.17】タグを指定してファイルをアップデートしてみる ▼ % cvs update -r TAGTEST1 tagtest.txt % cvs status tagtest.txt =================================================================== File: tagtest.txt Status: Up-to-date Working revision: 1.1 Thu Jan 25 22:20:11 2001 Repository revision: 1.1 /home/cvsroot/cvstest/tagtest.txt,v Sticky Tag: TAGTEST1 (revision: 1.1) Sticky Date: (none) Sticky Options: (none) (ファイル編集) % cvs commit -m "Sticky Test" tagtest.txt cvs commit: sticky tag `TAGTEST1' for file `tagtest.txt' is not a branch cvs [commit aborted]: correct above errors first! ▲ まず、さっきつけたタグTAGTEST1を指定してupdateコマンドを実行してみます【図4.17 1行目】。このとき、ぱっと見てはわからないのですが、statusコマンドを実行すると、Sticky Tagというところに、TAGTEST1 (revision: 1.1)というのがでてくるようになります。ちなみに、リビジョンや日付を指定してもSticky Tagにその情報が設定されます。このSticky Tagが設定された状態で、編集しコミットしようとしても、「StickyタグTAGTEST1はブランチじゃないよ!」と怒られてコミットできません【図4.17 12-14行目】。 ちなみに、ブランチの場合はコミットできます。ブランチについては、6章で説明します。 ■■■■Stickyタグを解除するには こんな状態に陥ったらどうしたらよいんでしょうか。この、Stickyタグはupdateコマンドを使って削除することができます。【図4.18】のように、オプション-Aをつけてupdateコマンドを実行します。そのあとstatusコマンドを実行してみると、Stickyタグが外れていることがわかります【図4.18 7行目】。これで無事に編集がコミットできるようになりました。 【図4.18】Stickyタグの解除の仕方 ▼ % cvs update -A tagtest.txt M tagtest.txt % cvs status tagtest.txt =================================================================== File: tagtest.txt Status: Locally Modified Working revision: 1.1 Thu Jan 25 22:20:11 2001 Repository revision: 1.1 /home/cvsroot/cvstest/tagtest.txt,v Sticky Tag: (none) Sticky Date: (none) Sticky Options: (none) % cvs commit -m "Undef Sticky Tag" tagtest.txt Checking in tagtest.txt; /home/cvsroot/cvstest/tagtest.txt,v <-- tagtest.txt new revision: 1.2; previous revision: 1.1 done ▲ ■■■■Stikyタグについてちょっとだけ ここで、ほんの少しだけ、StickyタグについてCVSが何をしているのか見てみましょう。updateコマンドで、タグや日付を指定したときに、何が起こっているのでしょうか。CVSディレクトリのファイルEntriesにその影響が出ています。ちょっと見てみましょう。【図4.19】は、タグを指定してアップデートしたときの例です。CVS/Entriesの中の当該ファイルの情報をファイル名でUNIXの一般的なコマンドであるgrepを使って抜き出してみましょう【図4.19 3行目】。この情報の最後にタグを意味するT一文字を頭にくっつけたタグの名前がついているのがわかると思います。 【図4.19】StickyタグとCVS/Entries ▼ % cvs update -r TAGTEST1 tagtest.txt U tagtest.txt % grep tagtest.txt CVS/Entries /tagtest.txt/1.1/Tue Jan 30 13:19:32 2001//TTAGTEST1 ▲ 【図4.20】は日付を指定してアップデートしてみた例です。同様に、日付を意味するDを頭につけて日付の具体的な値が入っているのがわかると思います。リビジョン番号を指定すれば、リビジョン番号が入ります。ここがSticky TagとSticky Dateの場所なのですね。 【図4.20】Sticky DateとCVS/Entries ▼ % cvs update -D "Jan 28 2001" tagtest.txt U tagtest.txt % cvs status -v tagtest.txt =================================================================== File: tagtest.txt Status: Up-to-date Working revision: 1.3 Thu Jan 25 22:53:23 2001 Repository revision: 1.3 /home/cvsroot/cvstest/tagtest.txt,v Sticky Tag: (none) Sticky Date: 2001.01.28.11.01.00 Sticky Options: (none) Existing Tags: TAGTEST1 (revision: 1.1) % grep tagtest.txt CVS/Entries /tagtest.txt/1.3/Thu Jan 25 22:53:23 2001//D2001.01.28.11.01.00 ▲ ■■■■まとめ ●タグをつけるには(作業コピーを使う場合) 作業コピー内に入る ↓ cvs tag TAGNAME ●タグをつけるには(リポジトリを指定する場合) cvs -d /home/cvsroot rtag TAGNAME module ●タグがついているか確認するには 作業コピー内に入る ↓ cvs status -v ●タグを利用してcheckoutするには(そして編集したい場合) cvs -d /home/cvsroot checkout -r TAGNAME module ↓ 作業コピー内に入る(cd module) ↓ cvs update -A ●タグを利用してupdateするには(そして編集したい場合) 作業コピー内に入る ↓ cvs update -r TAGNAME ↓ cvs update -A ■■■4.2.2 自分の作業状態を眺めてみよう 共同作業をしているときはもちろんですが、自分一人で作業している場合でも、ちょっと間が空いたりすると作業内容をすっかり忘れてしまうことはよくあります(少なくとも私はそうです。トリ頭)。昨日の自分は今日の他人、作業内容は確認できないといけません。CVSでコマンドを通しておこなった作業はリポジトリ内に記録されており、historyコマンドで確認することができます。ファイルの履歴内容が知りたければlogやannotateといったコマンドが利用できるでしょう。また、コミットされてないファイルについてはupdateコマンドで確認できますし、さらにファイルの状況について詳細が知りたければstatusコマンドでも確認できます。そしてコミット前のファイルと前のバージョンとの比較や、コミットされたファイルでもバージョン間の比較はdiffコマンドでおこなうことができます。 ■■■■これまで、どんな作業をしたか見てみよう historyコマンドを利用するとよいです。historyコマンドではリポジトリに対しておこなわれた「全て」の操作について、色々な形式で見ることができます。 【図4.21】historyコマンドの書式 ▼ cvs history [-レポート内容] [-フラグ] [-オプション 引数] [ファイル群...] ▲ オプションは沢山ありすぎるので、ここではいくつか紹介するだけにします。ちなみに、オプションなしで実行すると、自分のチェックアウトしたモジュールの一覧が出てくるだけです【図4.22】。 【図4.22】オプションなしで実行 ▼ cvs history O 01/18 11:25 +0000 mika CVSROOT =CVSROOT= ~/tmp/* ▲ -e(everything)オプションを使うと、すべての操作が時系列にそのまま表示されます。ちょっと見てみましょう【図4.23】。長いので途中省略しましたが、このような出力がずらずらと出てきます。一行に一つのイベント(おこなわれた操作)が表示されます。まず先頭に、イベントの種類が示されます。次に日付と時刻。その次がユーザ名です。あとは対象モジュールやリビジョンなどの情報になり、操作毎に異なります。 【図4.23】-eオプションつきで実行 ▼ % cvs history -e O 12/15 09:35 +0000 mika cvstest =cvstest= ~/tmp/* O 12/15 09:36 +0000 mika cvstest2 =cvstest2= ~/tmp/* A 12/16 02:03 +0000 mika 1.1 test.txt cvstest == ~/tmp/cvstest (中略) M 01/18 11:34 +0000 mika 1.2 cvswrappers CVSROOT == ~/tmp/CVSROOT A 01/18 11:35 +0000 mika 1.1 wrapnkf2 CVSROOT == ~/tmp/CVSROOT M 01/18 11:42 +0000 mika 1.12 config CVSROOT == ~/tmp ▲ イベントの種類は11個あり、「TOEFWUCGMAR」のどれか一文字で表されます。【表3.1】に各文字に対応するイベントをまとめておきます。 【表4.1】 文字 イベント T タグ O チェックアウト E エクスポート F リリース W 更新(ファイル削除) U 更新(ファイル上書き) C 更新(マージ、競合あり) G 更新(マージ、競合なし) M コミット(ファイル修正) A コミット(ファイル追加) R コミット(ファイル削除) この文字を組み合わせて、-x(extract?)オプションで指定することで、望むイベントだけ表示させることができます。たとえば、【図4.24】のようにします。ここでは、U=更新(ファイル上書き)イベントだけを抜き出してみました。他のイベントも同じように抜き出せますし、UOといったように複数文字指定して抜き出すこともできます。いろいろと試してみてください。 【図4.24】-xオプションでU=更新(ファイル上書き)イベントだけを見てみる ▼ cvs history -x U | less U 12/18 04:17 +0000 mika 1.2 tmp3.txt cvstest2/dir1 == ~/tmp/cvs test2/dir1 U 12/18 04:17 +0000 mika 1.1.1.1 tmp4.txt cvstest2/dir1/dir2 == ~/tmp/cvs test2/dir1/dir2 U 12/18 08:39 +0000 mika 1.2 tmp1.txt cvstest2 == ~/tmp/sub /cvstest2 (後略) ▲ ■■■■まとめ ●モジュールのチェックアウト状態を見るには 作業コピー内に入るかリポジトリを指定する ↓ cvs history ●全ての作業履歴を見るには 作業コピー内に入るかリポジトリを指定する ↓ cvs history -e ●特定のイベントの履歴を見るには 作業コピー内に入るかリポジトリを指定する ↓ cvs history -x イベント イベントの種類 文字 イベント T タグ O チェックアウト E エクスポート F リリース W 更新(ファイル削除) U 更新(ファイル上書き) C 更新(マージ、競合あり) G 更新(マージ、競合なし) M コミット(ファイル修正) A コミット(ファイル追加) R コミット(ファイル削除) ■■■■ファイルの履歴を見てみよう ファイルの履歴を知るためには、logというコマンドが使えます。logコマンドの書式は【図4.25】のようになります。 【図4.25】logコマンドの書式 ▼ cvs log [-lRhtNb] [-r[リビジョン(複数可)]] [-d 日付(複数可)] [ファイル群...] ▲ 管理ファイルconfigについてのログを見てみます【図4.26】。 【図4.26】CVSROOT/configに対するlogを調べる ▼ % cd CVSROOT % cvs log config RCS file: /home/cvsroot/CVSROOT/config,v Working file: config head: 1.12 branch: locks: strict access list: symbolic names: keyword substitution: kv total revisions: 12; selected revisions: 12 description: ---------------------------- revision 1.12 date: 2001/01/18 11:42:29; author: mika; state: Exp; lines: +1 -1 SystemAuth off ---------------------------- (中略) revision 1.2 date: 2001/01/01 12:00:14; author: mika; state: Exp; lines: +1 -1 TopLevelAdmin test for setting yes. ---------------------------- revision 1.1 date: 2000/12/14 05:48:47; author: mika; state: Exp; initial checkin ============================================================================= ▲ 12回更新して、そのすべてを見るのは大変なので、途中は省略してしまいました。最初の方にファイルの細かい情報が出てきて、「-」の区切り線の下から各リビジョンについての情報が続きます。リビジョンについての情報は3つの部分から成っていて、1行目がリビジョン番号、2行目がコミットされた日付、コミットした人、その時の状態と変化した行数になります。3行目以降がログメッセージです。ここでは、1.12の前1.11から1.3までは省略して、1.2と1.1を抜き出しています。最後「=」の区切り線が終わりを示しています。 特定のリビジョンを見たいときには、-rオプションを使います。たとえば、1.3だけ見たい場合は、-r1.3と指定します。 1.3と1.5が見たい場合には、-r1.3,1.5のように指定します。【図4.27】がその実行例です。 【図4.27】リビジョンを指定してlogを調べる ▼ % cd CVSROOT % cvs log -r1.3,1.5 config RCS file: /home/cvsroot/CVSROOT/config,v Working file: config head: 1.12 branch: locks: strict access list: symbolic names: keyword substitution: kv total revisions: 12; selected revisions: 2 description: ---------------------------- revision 1.5 date: 2001/01/11 22:43:56; author: mika; state: Exp; lines: +1 -1 Cancel PreservePermissions ---------------------------- revision 1.3 date: 2001/01/01 12:17:15; author: mika; state: Exp; lines: +1 -1 TopLevelAdmin is set to no. ============================================================================= ▲ ■■■■まとめ ●ファイル(targetfile)の全履歴を見るには 作業コピー内に入る ↓ cvs log targetfile ●ファイル(targetfile)の特定リビジョン(1.x)のログを見るには 作業コピー内に入る ↓ cvs log -r1.x targetfile ■■■■ファイル内の変更の構成を見てみよう annotateコマンドを利用して、あるリビジョンのファイルのどの部分がどのリビジョンで変更されたものなのかを知ることができます。annotateコマンドの書式は【図4.28】のようになります。 【図4.28】annotateコマンドの書式 ▼ cvs annotate [-lRf] [-r リビジョン|-D 日付] [ファイル群...] ▲ ちょっと、configファイルについてその構成を見てみましょう。【図4.29】の3行目*が15個並んでいる行の下からが、configの中身とそれに対する注釈(annotate)になっています。注釈は行毎に先頭に付加されています。たとえば、configファイルの1行目【図4.29 1行目】の注釈は、この行がリビジョン1.1で、それをコミットしたのがmikaというユーザで、コミットしたのは2000年12月14日であることを示しています。この行はそれから変化していないわけです。一方次の行は1.12ということで何回も変更されています。最後のコミットは2001年1月18日になっています。いつ書き換えたのかよくわかりますね(ふう)。 【図4.29】CVSROOT/configに対する注釈を調べる ▼ % cvs annotate config Annotations for config *************** 1.1 (mika 14-Dec-00): # Set this to "no" if pserver shouldn't check system users/passwords 1.12 (mika 18-Jan-01): SystemAuth=no 1.1 (mika 14-Dec-00): 1.1 (mika 14-Dec-00): # Set `PreservePermissions' to `yes' to save file status information 1.1 (mika 14-Dec-00): # in the repository. 1.11 (mika 18-Jan-01): PreservePermissions=no 1.1 (mika 14-Dec-00): 1.1 (mika 14-Dec-00): # Set `TopLevelAdmin' to `yes' to create a CVS directory at the top 1.1 (mika 14-Dec-00): # level of the new working directory when using the `cvs checkout' 1.1 (mika 14-Dec-00): # command. 1.10 (mika 12-Jan-01): TopLevelAdmin=yes ▲ ■■■■まとめ ●ファイル(targetfile)の変更の構成を見るには 作業コピー内に入る ↓ cvs annotate targetfile ■■■■ファイルの差分を見てみよう 今作業しているファイルとあるバージョン(リビジョン)がどのくらい違うのかとか、あるいは、あるリビジョンのファイルと他のリビジョンのファイルがどのくらい違うのかということがときどき気になることがあります。そういうことが知りたくなったときには、diffコマンドまたはrdiffを利用します。 diffの書式は、【図4.30】のようになります。一方、rdiffの書式は【図4.31】のようになります。 【図4.30】diffコマンドの書式 ▼ cvs diff [-lNR] [rcsdiffのオプション群] [[-r リビジョン1 | -D 日付1] [-r リビジョン2|-D 日付2]] [ファイル群...] ▲ 【図4.31】rdiffコマンドの書式 ▼ cvs rdiff [-lNR] [-c|-u] [-s|-t] [-V RCSバージョン] -r リビジョン1|-D 日付1 [-rリビジョン2|-D 日付2] [モジュール群...] ▲ ■■■■diffとrdiffの違い 一番の違いは、diffは作業コピーが必要なのに対して、rdiffは作業コピーを使用せずに直接リポジトリを操作するようになっているということです。このため、rdiffではリビジョンもしくは日付で少なくとも一つは比較対象を指定しなくてはなりませんし、リポジトリも指定する必要があります。また、今作業コピーに加えた変更を比較することはできません。そのかわり-sオプションで差分のサマリーをみたり、-tオプションで最新の2つのリビジョンを比較することができます。 また、diffではrcsdiffのオプションとして自分の環境のdiffコマンドで指定できるオプションが使えますが、rdiffでは使えません。diffでは、インストールの章で説明したように、GNUのdiffutilsパッケージを導入している場合には、-cなどのオプションが使用できます。これらの動作の違いを考慮した上で、目的に合わせた使いわけをしていくとよいでしょう。以下にいくつか、状況の例をあげてみます。GNU diffのオプションはうんざりするほどあります。 ■■■■今作業しているファイルと最後のコミットとを比べる 一番ありがちな状況です。diffを使いましょう。diffコマンドはリビジョンや日付の指定がない場合には、手元にある現在のファイルを最後にコミットされた状態と比べます。rdiffではこれはできません。ファイルを指定しないと、作業コピー内全てを対象にしてわずらわしいので、ここでは、difftest.txtというファイルを例に使います。このファイルの最新リビジョンの内容を【図4.32】に、その作業コピーをいじった後の内容を【図4.33】に示します。 【図4.32】最新の登録状態(最新リビジョンの内容) ▼ thisisapen this is a pen thisisapen ▲ 【図4.33】作業コピーの現状 ▼ thisisapen this is a pen this is a pen ▲ この状態で、特にオプションなしで実行した結果を【図4.34】に示します。なんだか、見づらい出力が出てきましたね。この出力は要するに2行目の後に空白行が挿入されて【7行目の2a3】、6行目にずれた5行目の内容が書き変わった(単語の間に空白が挿入された)【9行目の5c6】ということを言っているだけです。 【図4.34】オプションを指定しないで実行 ▼ % cvs diff difftest.txt Index: difftest.txt =================================================================== RCS file: /home/cvsroot/cvstest/difftest.txt,v retrieving revision 1.5 diff -r1.5 difftest.txt 2a3 > 5c6 < thisisapen --- > this is a pen ▲ これをもっと人間に見やすい形式で出力することもできます。大体コンテキスト形式を使用することが多いですが、ユニファイド形式という形式もあります。GNUのdiffが入っていればこれらの形式はサポートされているはずです。コンテキスト形式は-cオプション、ユニファイド形式は-uというオプションで指定することができます。【図4.35】と【図4.36】にそれぞれの実行例を示します。コンテキスト形式の方が見やすいでしょうか。いつも特定の形式で出したい場合には、.cvsrcにdiffのオプションを設定しておくとよいでしょう。 【図4.35】-cオプションを指定して実行 ▼ % cvs diff -c difftest.txt cvs diff -c difftest.txt Index: difftest.txt =================================================================== RCS file: /home/cvsroot/cvstest/difftest.txt,v retrieving revision 1.5 diff -c -r1.5 difftest.txt *** difftest.txt 2001/02/01 01:44:27 1.5 --- difftest.txt 2001/02/01 01:46:28 *************** *** 1,5 **** thisisapen this is a pen ! thisisapen --- 1,6 ---- thisisapen + this is a pen ! this is a pen ▲ 【図4.36】-uオプションを指定して実行 ▼ % cvs diff -u difftest.txt Index: difftest.txt =================================================================== RCS file: /home/cvsroot/cvstest/difftest.txt,v retrieving revision 1.5 diff -u -r1.5 difftest.txt --- difftest.txt 2001/02/01 01:44:27 1.5 +++ difftest.txt 2001/02/01 01:46:28 @@ -1,5 +1,6 @@ thisisapen + this is a pen -thisisapen + this is a pen ▲ ■■■■あるファイルについて任意の2つのリビジョンを比べてみる 比較対象がひとつのファイルで、UNIXコマンドのdiffを駆使した比較をおこないたい場合にはdiffを使いましょう。簡易な比較であれば、rdiffを使ってもかまいません。【図4.37】にdiffコマンドを使用した比較の例を示します。 【図4.37】diffコマンドで2つのリビジョンを指定して実行 ▼ % cvs diff -c -r1.1 -r1.2 difftest.txt Index: difftest.txt =================================================================== RCS file: /home/cvsroot/cvstest/difftest.txt,v retrieving revision 1.1 retrieving revision 1.2 diff -c -r1.1 -r1.2 *** difftest.txt 2001/02/01 00:37:39 1.1 --- difftest.txt 2001/02/01 00:44:07 1.2 *************** *** 1,4 **** thisisapen ! this is a pen this is a pen - this is a pen --- 1,3 ---- thisisapen ! this is a pen ▲ rdiffで同じことをするためには、リポジトリの指定とモジュールの先頭からのパスが必要です【図4.38】。ちなみに、rdiffの出力は何も指定しないと、コンテキスト形式で出てきます。 【図4.38】rdiffコマンドで2つのリビジョンを指定して実行 ▼ % cvs -d /home/cvsroot rdiff -r1.1 -r1.2 cvstest/difftest.txt Index: cvstest/difftest.txt diff -c cvstest/difftest.txt:1.1 cvstest/difftest.txt:1.2 *** cvstest/difftest.txt:1.1 Thu Feb 1 09:37:39 2001 --- cvstest/difftest.txt Thu Feb 1 09:44:07 2001 *************** *** 1,4 **** thisisapen ! this is a pen this is a pen - this is a pen --- 1,3 ---- thisisapen ! this is a pen ▲ ■■■■インデントの違いを無視した比較をおこなってみる ソースコードの場合には、空白というのは人間の読みやすさや好きずきのためにあってプログラム的にはほとんど意味をなしません。よってインデントの空白が4個だったのが8個になったからといって差分として表れるのは煩わしい、ということになります。そういう場合に、空白を無視するためのオプション-B、-b、-wがよく使われます。-Bオプションは空行の挿入削除だけによる違いを無視し、-bオプションは空白の数の増減だけによる違いを無視します。-wオプションは-bオプションの強力バージョンで、空白が一方にあって、他方にはない場合でも無視します。【図4.39】と【図4.40】は、前示したdifftest.txtについて-Bオプションと-wオプションをそれぞれ適用した結果です。 【図4.39】-Bの動作 ▼ % cvs diff -B difftest.txt Index: difftest.txt =================================================================== RCS file: /home/cvsroot/cvstest/difftest.txt,v retrieving revision 1.5 diff -B -r1.5 difftest.txt 5c6 < thisisapen --- > this is a pen ▲ 【図4.40】-wの動作 ▼ % cvs diff -w difftest.txt Index: difftest.txt =================================================================== RCS file: /home/cvsroot/cvstest/difftest.txt,v retrieving revision 1.5 diff -w -r1.5 difftest.txt 2a3 > ▲ -bオプションでは普通にdiffをかけた結果と同じになります。ですので、difftest.txtの4行目にちょっと空白を挿入した場合の変化について【図4.41】に示しましょう。オプションなしでは、空白の挿入による影響が結果に出ましたが、-bオプションをつけるとその影響が出ずに、前のdiffと同じ結果になります。 【図4.41】difftest.txtの4行目に空白を挿入して-bオプションの動作を調べる ▼ % cvs diff difftest.txt Index: difftest.txt =================================================================== RCS file: /home/cvsroot/cvstest/difftest.txt,v retrieving revision 1.5 diff -r1.5 difftest.txt 3d2 < this is a pen 5c4,6 < thisisapen --- > this is a pen > > this is a pen % cvs diff -b difftest.txt Index: difftest.txt =================================================================== RCS file: /home/cvsroot/cvstest/difftest.txt,v retrieving revision 1.5 diff -b -r1.5 difftest.txt 2a3 > 5c6 < thisisapen --- > this is a pen ▲ diffのオプションは他にもたくさんあります。自分の目的に合ったオプションを選んでdiffを活用してください。 ■■■■最新の2つのリビジョンを比べてみる モジュールの中に含まれる各ファイルについて最新のdiffやrdiffの-rオプションで指定するのは、実は結構めんどうです。あるファイルは最新が、1.11で違うファイルは1.2というようにバージョンがばらけている場合にいちいち指定するのは大変ですね。タグをつければ指定できますが、そこまでしたくないというのはあります。そんなときには、rdiffの-tオプションを使うのが便利です。cvstestというモジュールについて実行してみましょう。たくさん結果が出てくるので、【図4.42】では省略しています。difftest.txtの最新バージョンは1.5でその前のバージョンの1.4との比較が出てきます(が省略しています)。他のファイルについてもそれぞれ比較が出てきますが、rcskeytest.txtの1.2と1.3の比較だけ残してあとは省略しました。たくさん出てくる様子は実際にやってみてください。 【図4.42】rdiffを-tオプションつきで実行してみる ▼ % cvs -d /home/cvsroot rdiff -t cvstest Index: cvstest/difftest.txt diff -c cvstest/difftest.txt:1.4 cvstest/difftest.txt:1.5 *** cvstest/difftest.txt:1.4 Thu Feb 1 10:38:35 2001 --- cvstest/difftest.txt Thu Feb 1 10:44:27 2001 *************** *** 1,3 **** --- 1,5 ---- (中略) Index: cvstest/rcskeytest.txt diff -c cvstest/rcskeytest.txt:1.2 cvstest/rcskeytest.txt:1.3 *** cvstest/rcskeytest.txt:1.2 Sat Jan 20 20:24:49 2001 --- cvstest/rcskeytest.txt Sat Jan 20 20:48:02 2001 *************** *** 1,10 **** (後略) ▲ 残念ながら、この比較では-Bなどのこまごまとしたオプションは使えません。 ■■■■ある時点から変更が加えられたかどうか調べる 意外と知られていないのが、ある時点以降に加えられた変更の概要をrdiffの-sオプションで見ることができるということです。どのようにするかというと、【図4.43】のようにします。ここでは-Dオプションで日付を指定していますが、-rオプションでリビジョンを指定してもかまいません。モジュールcvstestについて、2001年の1月21日以降に加えられた変更の概要が一覧になって出てきているのがわかると思います。difftest.txtとrcskeytest2.txt、tagtest.txtの3つが新しく加えられ、hlink.txtとslink.txtがなくなり、rcskeytest.txtが変更されていてバージョン1.1から1.3に上がっているとメッセージに書かれています。これを利用して、プログラムのビルドを自動化するということをしている人もいるようです(変更があった場合チェックアウトしてクリーンビルドする)。 【図4.43】rdiffを-sオプションつきで実行してみる ▼ % cvs -d /home/cvsroot rdiff -s -D "20 Jan 2001" cvstest | less cvs rdiff: Diffing cvstest File cvstest/difftest.txt is new; current revision 1.5 File cvstest/hlink.txt is removed; not included in current release File cvstest/rcskeytest.txt changed from revision 1.1 to 1.3 File cvstest/rcskeytest2.txt is new; current revision 1.2 File cvstest/slink.txt is removed; not included in current release File cvstest/tagtest.txt is new; current revision 1.3 ▲ ■■■■まとめ ●ファイル(targetfile)について現在の状態と最新リビジョンとの違いを見るには 作業コピー内に入る ↓ cvs diff targetfile ●ファイル(targetfile)について2つのリビジョン(1.xと1.y)との違いを見るには 作業コピー内に入る ↓ cvs diff -r1.x -r1.y targetfile ●作業コピーを使わずにファイル(module/targetfile)について2つのリビジョン(1.xと1.y)との違いを見るには cvs -d /home/cvsroot rdiff -r1.x -r1.y module/targetfile ●あるモジュール(targetmodule)内のファイルについて最新の2つのリビジョンの違いを見るには cvs -d /home/cvsroot rdiff -t targetmodule ●あるモジュール(targetmodule)についてある時点(mm/dd/yy)から加えられた変更の概要を見るには cvs -d /home/cvsroot rdiff -s -D "mm/dd/yy" targetmodule ●その他使うと便利なdiffのオプション -c 人間の見やすいコンテキスト形式で出力 -B 空行の追加削除を無視 -b 空白の増減を無視(前の状態に空白はあること) -w 空白の増減を無視(前の状態に空白は無くてもよい) ■■■■ファイルの状態を見てみよう タグのところで既に使いましたが、ファイルの状態を見るには、statusコマンドを使います。statusコマンドの書式は【図4.45】のようになります。 【図4.45】statusコマンドの書式 ▼ cvs status [-vlR] [ファイル群...] ▲ よく使うオプションは-vオプションです。他には大したオプションはありません。オプションを指定しないと、【図4.46】のようになります。 【図4.46】オプションを指定しないで実行 ▼ =================================================================== File: tagtest.txt Status: Up-to-date Working revision: 1.2 Thu Jan 25 22:25:08 2001 Repository revision: 1.2 /home/cvsroot/cvstest/tagtest.txt,v Sticky Tag: (none) Sticky Date: (none) Sticky Options: (none) ▲ -vオプションを指定するとタグ情報まで見ることができます。つまり、そのファイルにつけられたタグを一覧として見ることができます。【図4.47】が、その実行例です。 【図4.47】-vオプションを指定して実行 ▼ % cvs status -v tagtest.txt =================================================================== File: tagtest.txt Status: Up-to-date Working revision: 1.2 Thu Jan 25 22:25:08 2001 Repository revision: 1.2 /home/cvsroot/cvstest/tagtest.txt,v Sticky Tag: (none) Sticky Date: (none) Sticky Options: (none) Existing Tags: TAGTEST1 (revision: 1.1) ▲ ■■■■まとめ ●ファイル(targetfile)について状態を見るには 作業コピー内に入る ↓ cvs status targetfile ●ファイル(targetfile)についてタグ情報まで含めた状態を見るには 作業コピー内に入る ↓ cvs status -v targetfile ■■■4.2.3 エクスポート(export) CVSの管理情報を省いた形でファイル群を取り出すにはexportというコマンドを使います。checkoutと同様に、-rオプションや-Dオプションを指定してスナップショットを取ることができます。exportコマンドの書式は【図4.48】のようになります。 【図4.48】exportコマンドの書式 ▼ cvs export [-NRfln] [-rリビジョン|-D 日付] [-d ディレクトリ] [-k 置換モード]モジュール... ▲ 例えば、最新スナップショットを取る場合には日付に未来の日付(たとえば明日)を指定するのが無難です。つまり、【図4.49】のように-Dオプションにtomorrowを指定して実行します。とすると、cvstestモジュールが取り出されます。 【図4.49】最新のcvstestモジュールを取り出す ▼ % cvs export -D tomorrow cvstest cvs export: Updating cvstest U cvstest/difftest.txt U cvstest/fish.jpg U cvstest/fish2.jpg U cvstest/rcskeytest.txt U cvstest/rcskeytest2.txt U cvstest/tagtest.txt U cvstest/test.bin U cvstest/test.txt U cvstest/test2.txt ▲ 【図4.49】では、cvstestとモジュール名そのままで取り出されます。 exportコマンドでは上書きはできませんので、自動化するような場合には削除したり、ディレクトリ名を変えたりといった細工が必要になります。スナップショットを自動化するような場合には、たとえば日付を付加したようなディレクトリ名をつけたい、というようなことがあるかも知れません。このようなとき、-dオプションを使用すると簡単です。 ディレクトリ名をたとえば、cvstest_010131とすると、【図4.50】のように実行します。付加する日付の生成についてはスクリプトでがんばらないといけませんけどね。 【図4.50】-dオプションを使って名前を変える ▼ % cvs export -d cvstest_010131 -D tomorrow cvstest cvs export: Updating cvstest_010131 U cvstest_010131/difftest.txt U cvstest_010131/fish.jpg U cvstest_010131/fish2.jpg U cvstest_010131/rcskeytest.txt U cvstest_010131/rcskeytest2.txt U cvstest_010131/tagtest.txt U cvstest_010131/test.bin U cvstest_010131/test.txt U cvstest_010131/test2.txt ▲ ■■■■まとめ ●あるモジュール(targetmodule)の最新をCVSの情報なしに取り出すには cvs -d /home/cvsroot export -D tomorrow targetmodule ●あるモジュール(targetmodule)の最新をCVSの情報なしにnewdirディレクトリに取り出すには cvs -d /home/cvsroot export -D tomorrow -d newdir targetmodule ■■■4.2.4 RCSキーワードを活用しよう ■■■■RCSキーワードって何? CVSはある特定の文字列がファイルに含まれていると、checkoutやupdateなど作業コピーを取り出す際に、その文字列をルールに従って置き換えます。これは、元々はCVSの基になったRCSが提供していた機能ですので、その特定の文字列のことをRCSキーワードと呼んでいます。 RCSキーワードは、【表3.2】のように11個あります。 【表3.2】 RCSキーワード キーワードの意味 $Name:$ Stikyタグの名前 $Author$ コミットした人 $Date$ コミットした日付 $Revision$ リビジョン $RCSfile$ ,vのついたファイル(RCSファイル)名 $Source$ ソースファイル名(絶対パス) $Log$ ログメッセージ $State$ 状態 $Locker$ ロックをかけている人がいればその人 $Id$ 上の組合せ($RCSfile$ $Revision$ $Date$ $Author$ [$Locker$]) $Header$ 上の組合せ ちょっと、ファイルを作って試してみましょう。図4.51のようなファイルを用意します。名前は、rcskeytest.txtです。 【図4.51】のようなファイルを用意します。名前は、rcskeytest.txtです。 【図4.51】rcskeytest.txtの中身 ▼ $Name$はStikyタグの名前。 $Author$はコミットした人。 $Date$はコミットした日付。 $Revision$はリビジョン。 $RCSfile$は,vのついたファイル(RCSファイル)名。 $Source$はソースファイル名(絶対パス) $Log$はログメッセージ。 $State$は状態。 $Locker$はロックをかけている人がいればその人。 $Id$は上の組合せ。 $Header$は上の組合せ。 ▲ これを登録してみます。いつものようにaddコマンドとcommitコマンドを実行して登録します【図4.52】。 【図4.52】rcskeytest.txtを登録する ▼ % cvs add -m "RCS Keywords Test File" rcskeytest.txt cvs add: scheduling file `rcskeytest.txt' for addition cvs add: use 'cvs commit' to add this file permanently % cvs commit -m "RCS Keywords Test" rcskeytest.txt RCS file: /home/cvsroot/cvstest/rcskeytest.txt,v done Checking in rcskeytest.txt; /home/cvsroot/cvstest/rcskeytest.txt,v <-- rcskeytest.txt initial revision: 1.1 done ▲ ファイルはどんな風になったでしょうか。【図4.53】のようになっているはずです。 【図4.53】登録後の中身 ▼ $Name: $はStickyタグの名前。 $Author: mika $はコミットした人。 $Date: 2001/01/18 17:37:39 $はコミットした日付。 $Revision: 1.1 $は リビジョン。 $RCSFiles$は,vのついたファイル(RCSファイル)名。 $Source: /home/cvsroot/cvstest/rcskeytest.txt,v $はソースファイル名(絶対パス) $Log: rcskeytest.txt,v $ Revision 1.1 2001/01/18 17:37:39 mika RCS Keywords Test はログメッセージ。 $State: Exp $は状態。 $Locker: $はロックをかけている人がいればその人。 $Id: rcskeytest.txt,v 1.1 2001/01/18 17:37:39 mika Exp $は上の組合せ。 $Header: /home/cvsroot/cvstest/rcskeytest.txt,v 1.1 2001/01/18 17:37:39 mika Exp $は上の組合せ。 ▲ このうち、よく使われるのは$Id$です。ソースコードファイルの先頭にコメントとして埋め込まれたり、バージョン文字列として埋め込まれたりします。自分の目的に合わせて利用してみてください。 ■■■■文字列を置換して欲しくないんだけど ファイルに埋め込まれたRCSキーワードを置換したくない場合があります。例えば、バイナリファイルや、本書の原稿のようなファイルがこれに該当します。 なお、バイナリファイルについては続く4.2.5項で説明しますが、ここで紹介する方法と同様の処理をおこないます。 RCSキーワードを置換しないためには、addコマンドでファイルを追加するときにRCSキーワードの置換方法についてのフラグを-kオプションで設定します。うっかり、addするときに指定し忘れた場合には、後でadminコマンドを使って変更することもできます。 指定できる置換方法とその意味を【表3.3】に示します。おおまかにいうと、バイナリモード以外は、キーワードに置き換えるkと値に置き換えるvとその組み合わせkvです。kvlはキーワードと値だけでなくロックもかけるのですが、あまり使いません。oは一つ前に戻すということのようです。詳細については付属マニュアルの「キーワード置換(Keyword substitution)」の中の「置換モード(Substitution modes)」の項を見てください。 【表3.3】キーワードの置換方法 b binaryバイナリファイル k keywordキーワードのみ o old前の状態に v value値のみ kv keyword+valueキーワードと値(標準) kvl keyword+value+lockキーワードと値とロック では、RCSキーワードを展開したくなければ、addコマンドに-kkをつければよいのでしょうか? 先ほど登録したファイルと同じものを、rcskeytest2.txtという名前で作成して、それを-kkで登録してみましょう【図4.54】。 【図4.54】rcskeytest2.txtを登録する ▼ % cvs add -kk -m "RCS Keyword Test 2" rcskeytest2.txt cvs add: scheduling file `rcskeytest2.txt' for addition cvs add: use 'cvs commit' to add this file permanently % cvs commit -m "RCS Keyword Test 2" rcskeytest2.txt RCS file: /home/cvsroot/cvstest/rcskeytest2.txt,v done Checking in rcskeytest2.txt; /home/cvsroot/cvstest/rcskeytest2.txt,v <-- rcskeytest2.txt initial revision: 1.1 done ▲ ここで、rcskeytest2.txtを覗いてみると、なんでか$Log$だけは置換されてしまいます【図4.55】。残念ですが、$Log$も置換しないようにするためには、b(binary)を指定するしかないようです。 【図4.55】なぜ、$Log$だけ置換されるのだろう… ▼ $Name$はStikyタグの名前。 $Author$はコミットした人。 $Date$はコミットした日付。 $Revision$はリビジョン。 $RCSfile$は,vのついたファイル(RCSファイル)名。 $Source$はソースファイル名(絶対パス) $Log$ Revision 1.2 2001/05/28 06:54:55 misty RCS Keyword Test 2 はログメッセージ。 $State$は状態。 $Locker$はロックをかけている人がいればその人。 $Id$は上の組合せ。 $Header$は上の組合せ。 ▲ 置換モードは、addとadminの他にcheckout、diff、export、rdiff、updateコマンドでも指定することができます。addとadminがリポジトリの,vファイル(RCSファイル)の中に置換モードを設定するのと違って、これらはコマンド実行時の置換モードや作業コピーでの置換モードを設定します。 たとえば、checkoutやupdateでファイル毎に置換モード設定をすると、CVS/Entriesの行の最後から2番目のフィールドにモードが設定されるようになります。 fish2.jpgというファイルを何も指定せずに登録したとして、updateコマンドで-kbでバイナリモードとして設定してみたときの、CVS/Entriesでの当該ファイルについての情報の変化を【図4.56】に示します。 【図4.56】CVS/Entriesの変化 ▼ % grep fish2.jpg CVS/Entries /fish2.jpg/1.1/Thu Feb 15 01:13:20 2001// % cvs update -kb fish2.jpg U fish2.jpg % grep fish2.jpg CVS/Entries /fish2.jpg/1.1/Thu Feb 15 01:20:29 2001/-kb/ ▲ adminコマンドでの置換モードの変更は、バイナリファイルの取り扱いのところでもう少し詳しく見てみます。 ■■■■まとめ ●あるファイル(targetfile)内で置換キーワードを使用するには targetfileに置換キーワードを埋め込む ●あるファイル(targetfile)にある置換モード(mode)を指定して登録するには 作業コピー内に入る ↓ cvs add -kmode targetfile ●あるファイル(targetfile)について作業コピー内だけ置換モードをmodeに変更するには 作業コピー内に入る ↓ cvs update -kmode targetfile ■■■4.2.5 テキストファイル以外のファイルを扱ってみよう ■■■■バイナリファイルは扱えるの? 前にも書いたように、扱えはしますが、得意ではありません。これは、CVSのバージョン管理では、もともとテキストファイルの差分を管理するためです。バイナリファイルの場合、CVSは同じように差分で管理しようとしますが、それほど嬉しくはありません。ちょっと、テキストファイル(test.bin)とJPEGファイル(fish.jpg)をバイナリファイルを登録してみます。バイナリファイルを登録するときのポイントは、addの-kオプションでbフラグを指定することです。 オプション-kはRCSキーワード置換モードを指定するためのオプションです。上で説明したように、CVSはコミット時に、RCSキーワードを展開します。これをバイナリファイルに対しておこなったらどうなるでしょう。つまり、偶然に$Id$という文字列がバイナリファイルに含まれていたら、CVSは問答無用に、$Id: ...という文字列に展開します。とすると、バイナリファイルはそこで壊れてしまいます。これを制御するのが、-kオプションです。たとえばbフラグの場合はファイルをバイナリとして扱い展開しないようにします。なお、この指定をおこなった場合には、PC(WindowsおよびMacintosh)クライアントとのやりとりでの改行コード変換もおこないません。 試しに画像ファイル(JPEGファイル)のfish.jpgというのを登録してみましょう。addコマンドに-kbをつけて登録します【図4.57】。 【図4.57】バイナリファイルの追加 ▼ % cvs add -kb -m "JPEG File" fish.jpg cvs add: scheduling file `fish.jpg' for addition cvs add: use 'cvs commit' to add this file permanently % cvs update cvs update: Updating . A fish.jpg % cvs commit -m "JPEG File Commit" fish.jpg RCS file: /home/cvsroot/cvstest/fish.jpg,v done Checking in fish.jpg; /home/cvsroot/cvstest/fish.jpg,v <-- fish.jpg initial revision: 1.1 done % ls -F CVS/ fish.jpg test.bin test.txt test2.txt ▲ ここで、fish.jpgを編集して、新たに1.2として登録します。このときリポジトリの中のRCSファイル/home/cvsroot/cvstest/fish.jpg,vのサイズ(7938バイト)は最初のfish.jpgのサイズ(4954バイト)と新しいサイズ(4945バイト)を足したもの(9899バイト)よりは幾分か小さくなっています。多少の効果はあるみたいですね。 【図4.58】サイズを比較してみる ▼ % ls -l fish.jpg -rw-r--r-- 1 mika wheel 4954 12月31 02:38 fish.jpg (編集、コミット) % ls -l fish.jpg -rw-r--r-- 1 mika wheel 4945 12月31 02:42 fish.jpg % ls -l /home/cvsroot/cvstest/fish.jpg,v -r--r--r-- 1 mika wheel 7939 12月31 02:43 /home/cvsroot/cvstest/fish.jpg,v ▲ ちなみに、ここで/home/cvsroot/cvsroot/fish.jpg,vを覗いてみると、なんとか差分で管理しようとしている様子がうかがえます。ずらずら書いてもうっとうしいので書きませんが、興味のある人は覗いてみてください。 ■■■■モジュール登録する時に混ざったバイナリファイルについてはどうすればいいの? importコマンドで、既にあるファイル群をまとめて登録する時に、その中にバイナリファイルが混ざっていたらどうしましょうか。一旦登録して、後から次に紹介するadminコマンドで一つ一つ変えていくという手もありますが、気が遠くなりますね。そういうときは、wrappersの機能を使ってまとめるのが比較的簡単です。オプションで指定する方法、cvswrappers(.cvswrappers)であらかじめ指定しておくという方法があります。まず、オプションで指定する方法を紹介しましょう。登録したいファイル群の中に、.jpg、.JPG、.gif、.GIFというサフィックスを持つバイナリファイルが含まれているとしましょう。そういう時には、【図4.59】のようにファイルのパターンと-k'b'を並べた文字列を持つ-Wオプションを並べて指定します。このとき、-kbとしてはいけません。うまくいきません。【図4.59】ではそれぞれのサフィックスを持つ4つのファイルを用意しています。3行目は長くなったので\で折り返していますが、続けて入力してもらって構いません。 【図4.59】-Wオプションでバイナリファイルのimportを簡単にする ▼ % ls fish.gif fish.jpg fish2.GIF fish2.JPG % cvs -d /home/cvsroot import -W "*.jpg -k'b'" -W "*.JPG -k'b'" \ -W "*.gif -k'b'" -W "*.GIF -k'b'" -m "Binary test module" \ bintest mikamama BINTEST_1 N bintest/fish.gif N bintest/fish.jpg N bintest/fish2.GIF N bintest/fish2.JPG ▲ これをチェックアウトして確かめてみる【図4.60】と、bintest/CVS/Entriesでちゃんと、-kbがついていることがわかります【図4.60 7行目-11行目】。 【図4.60】checkoutして状態を確かめる ▼ % cvs -d /home/cvsroot checkout bintest cvs checkout: Updating bintest U bintest/fish.gif U bintest/fish.jpg U bintest/fish2.GIF U bintest/fish2.JPG % cat bintest/CVS/Entries /fish.gif/1.1.1.1/Wed Feb 14 12:00:51 2001/-kb/ /fish.jpg/1.1.1.1/Wed Feb 14 12:00:51 2001/-kb/ /fish2.GIF/1.1.1.1/Wed Feb 14 12:00:51 2001/-kb/ /fish2.JPG/1.1.1.1/Wed Feb 14 12:00:51 2001/-kb/ D ▲ 正確にはリポジトリ内の,vファイル(RCSファイル)の中に設定されているので、そちらも確認してください。expandという文字列を含む行に設定されています。,vファイルの中からgrepで抜き出してみましょう【図4.61】。細かい話ですが、grepの-aオプションはバイナリファイルを強制的に検索するオプションです。 【図4.61】,vファイルの状態を確かめる ▼ grep -a expand /home/cvsroot/bintest/*,v /home/cvsroot/bintest/fish.gif,v:expand @b@; /home/cvsroot/bintest/fish.jpg,v:expand @b@; /home/cvsroot/bintest/fish2.GIF,v:expand @b@; /home/cvsroot/bintest/fish2.JPG,v:expand @b@; ▲ cvswrappers(.cvswrappers)を使う方法もあります。-Wオプションで指定した文字列を、一行ずつ並べるだけです。バイナリファイルの登録を頻繁におこなうようであれば、設定しておいた方が楽でしょう。ちなみに、Wordのファイルなど制御文字の入った文書もバイナリ指定しておく必要があります。Windowsを主に使っている人でCVSをバックアップに使いたい場合には、サフィックスをcvswrappersに登録しておいた方がよいでしょう。 【図4.62】cvswrappersの記述 ▼ *.gif -k'b' *.GIF -k'b' *.jpg -k'b' *.JPG -k'b' ▲ 【図4.62】のように指定した後は、importの時に-Wオプションで指定しなくても、また、addの実行時に-kbオプションをつけなくても、自動的につけられるようになります。【図4.63】にaddの実行例を示します。commitコマンドの-mオプションの中はコメントですので関係ありません。CVS/Entriesからgrepで新規に追加したfish3.jpgファイルについての情報を抜き出してみると、確かに-kbがついていることがわかります。また、,vファイルの方も設定されているようです。 【図4.63】cvswrappersに書いておけば指定する必要がない ▼ % cvs add -m "New fish jpeg file" fish3.jpg cvs add: scheduling file `fish3.jpg' for addition cvs add: use 'cvs commit' to add this file permanently % cvs commit -m "Cvswrappers -k'b' test for jpeg file" fish3.jpg RCS file: /home/cvsroot/bintest/fish3.jpg,v done Checking in fish3.jpg; /home/cvsroot/bintest/fish3.jpg,v <-- fish3.jpg initial revision: 1.1 done % grep fish3.jpg CVS/Entries /fish3.jpg/1.1/Wed Feb 14 12:07:59 2001/-kb/ % grep -a expand /home/cvsroot/bintest/fish3.jpg,v expand @b@; ▲ ■■■■後からバイナリファイルとして扱うにはどうすればよいの? addやimportでリポジトリに登録するときに-kbを指定し忘れて困ることがあります。キーワード置換のところで書いたようにcheckoutやupdateコマンドの実行時に-kbを指定することにより、作業コピー内だけでバイナリファイル扱いするように設定することもできます。この場合リポジトリ内の,vファイルの設定は変わらず、CVS/Entriesの設定だけが変わります。しかしこれだと、なんとなく冴えません。やはり、リポジトリ内の,vファイルにちゃんとバイナリファイル扱いするように指定したいです。そういう場合には、adminコマンドを使用します。addと同じように、-kオプションでモードを指定することによって、リポジトリ内の,vファイルに記述された置換モードを設定し直すことができます。バイナリファイルにするには、-kbです。【図4.64】にfish4.pngというファイルをそのまま登録してしまった場合の再設定の様子を示します。まず1行目で、fish4.png,vにexpandが設定されなかったということを調べた後、adminに-kbを指定して再設定します【2行目】。次に【5行目】でfish4.png,vを確認すると、確かにexpandが設定されていることがわかります【6行目】。 【図4.64】置換モードの再設定 ▼ % grep -a expand /home/cvsroot/bintest/fish4.png,v % cvs admin -kb fish4.png RCS file: /home/cvsroot/bintest/fish4.png,v done % grep -a expand /home/cvsroot/bintest/fish4.png,v expand @b@; ▲ ■■■■まとめ ●あるファイル(targetfile)をバイナリファイルとして登録するには 作業コピー内に入る ↓ cvs add -kb targetfile ●あるモジュール(targetmodule)をその中のあるサフィックス(.x)を持つファイルについてはバイナリファイルとして登録するには cvs -d /home/cvsroot import -W "*.x -k'b'" targetmodule ベンダー名 バージョン名 ●あるファイル(targetfile)を後からバイナリファイルに再設定するには 作業コピー内に入る ↓ cvs admin -kb targetfile ■■■■特殊ファイルは扱えるの? 扱えないこともありませんが、設定をしなければいけません。設定しなければ当然うまくいきませんし、設定しても、望んだ挙動にはなるとは限りません。デバイスファイルのようなハードウェアに依存するようなファイルはそもそもCVSで扱おうとするのがおかしいという話もあります。 シンボリックリンクファイルとハードリンクファイルは扱えると便利な気もしますが、これもUNIXのファイルシステムに依存しているので、CVSで扱おうとするのは無理があります。リポジトリに登録はできますが、通常のファイルとしてであって、リンクとしての機能は失われます。たとえば【図4.65】では、test.txtに対してlinktest.txtをシンボリックリンクファイルとして、hard_link.txtをハードリンクファイルとして作成しています【1-2行目】。lsコマンドの-iオプションはinodeというファイルの識別番号を表示するためのコマンドですが、ハードリンクファイルであるhard_link.txtの場合は、test.txtと同じになっていることに注目してください【5行目】。 【図4.65】シンボリックリンクファイルとハードリンクの作成(設定前) ▼ % ln -s test.txt linktest.txt % ln test.txt hard_link.txt % ls -Fi 228515 CVS/ 228569 linktest.txt@ 228520 test2.txt 228528 hard_link.txt 228528 test.txt (登録して、別の作業コピーを取り出す) % ls -Fi 49235 CVS/ 81877 linktest.txt* 81879 test2.txt 81876 hard_link.txt 81878 test.txt ▲ シンボリックリンクをどうしても扱いたい場合には、管理ファイルのconfigでPreservePermissions=yesとしてみることはできます。CVSのバージョン1.10.8でテストした結果を【図4.66】に示します。この結果では、シンボリックリンクはうまく動作しましたが、ハードリンクについては望んだ結果は得られませんでした。つまり、ハードリンクではinodeが一致しなければならないのに、一致しませんでした。また、PreservePermissionsを切り替えているとcommitできなくなったり挙動がおかしくなりました。今のところ使わない方が無難なようです。 【図4.66】シンボリックリンクとハードリンクの作成(設定後) ▼ % ln -s test.txt slink.txt % ln test.txt hlink.txt % ls -Fi 228515 CVS/ 228573 slink.txt@ 228520 test2.txt 228528 hlink.txt 228528 test.txt % cvs add -m "Links" slink.txt hlink.txt cvs add: scheduling file `slink.txt' for addition cvs add: scheduling file `hlink.txt' for addition cvs add: use 'cvs commit' to add these files permanently % cvs commit -m "Link Test" cvs commit: Examining . RCS file: /home/cvsroot/cvstest/hlink.txt,v done Checking in hlink.txt; /home/cvsroot/cvstest/hlink.txt,v <-- hlink.txt initial revision: 1.1 done RCS file: /home/cvsroot/cvstest/slink.txt,v done Checking in slink.txt; /home/cvsroot/cvstest/slink.txt,v <-- slink.txt initial revision: 1.1 done % ls -Fi 81876 CVS/ 81887 slink.txt@ 81890 test2.txt 81884 hlink.txt 81889 test.txt ▲ ■■■■まとめ ●シンボリックリンクファイルを取り扱うには 管理ファイルconfigでPreservePermissions=yesとする(不安定)