[Shell] バージョン管理

ソースコードの「バージョン管理」はとても便利で有意義な手段である。プログラムをどんどん書き換えていろいろ試し、うまく行かなかったらまた元に戻すとか、先輩の書いたプログラムを元にして機能を拡張したプログラムを作るなどの場合にその力を発揮するので、特に卒論生など、まだプログラミングを学びはじめたばかりの研究者にはお勧めしたい。

このページでは、特にCVSの初歩的な使い方についてのみ紹介する。

「研究に使うUNIXとその機能」のページから独立 (2000/8/2)
CVS関係のリンク、参考文献を追加 (2000/10/4)

[back!] 研究に使うUNIXとその機能
[go!] シェル


* バージョン管理の意義

プログラムを改良しようとしてソースファイルの編集をすると、誤ってバグを埋め込んでしまったり、ひどいときにはプログラムが動かなくなることもあります。このようなときにも、編集前のプログラムを保存しておけばすぐに以前の状態に戻せます。また、編集後のプログラムを前のものと比較すれば、どんな誤りを犯しているかも調べられるでしょう。つまり、プログラムを編集するときには、以前のバージョンを保存しておくことが重要となるわけです。

これらのためにはすべてのバージョンをコピーしておく方法が考えられますが、それぞれのバージョンとファイル名の対応の管理や各バージョンがどんなものかの記録が必要となります。たとえば、"機能Aは実現したが機能Bの実現に着手する前のバージョン"を見たいと思ったときに、実際にどのバージョン (ファイル)を見ればよいかは、これらの記録がないと判断できません。また、 1人でプログラムの開発を進める場合は問題となりませんが、複数の人間が携わっていると"誰が" "いつ"編集したかが重要になります。さらに、複数の人間が同じファイルを編集してしまう可能性もあります(通常は、どちらかの変更が無効となります)。

このような問題に対処するためのシステムがバージョン管理システムです。これを用いれば、

などがおこなえます。

(UNIX MAGAZINE 1993年10月号 "UNIX流プログラミング" より)

* この節で説明すること、しないこと

この節では、すでにある保管庫からコンテンツ(モジュール)を取り出し、必要に応じて変更を加え、その内容を再び保管庫に登録する方法を説明します。 CVSのインストール、保管庫(リポジトリ)の作成とコンテンツの登録については説明しません

なおCVSで管理しているコンテンツ(プロジェクト)のことを、 CVS用語では「モジュール」(module)といいます。

* 下準備 - 環境変数

CVSの保管庫(リポジトリ)がある位置を、環境変数CVSROOT に指定します。保管庫の位置は、CVSの管理者に問い合わせてください。たとえば保管庫が/home/project/cvsrootにあるときは、以下のようにして設定します。

csh, tcshなどの場合
setenv CVSROOT /home/project/cvsroot
sh, bash, zshなどの場合
CVSROOT=/home/project/cvsroot; export CVSROOT

流体研の利用者へ: 流体研の標準的な環境では、上記環境変数はすでにセットされているはずですので、改めて設定する必要はありません。

* 保管庫からモジュールを取り出す

CVSの操作には、そのものずばりcvs(1)というコマンドを用いる。モジュールを取り出すときは、まずモジュール名を知る必要がある。プロジェクトの管理者やまわりの先輩に聞こう。

モジュール名が分かったら、 "cvs checkout"コマンドでそのモジュールを保管庫から取り出す。たとえばfluidlab/DMDFというモジュールを取り出す方法は、以下のとおり。

% cvs checkout fluidlab/DMDF

…そのまんまですね。

このコマンドでfluidlab/DMDFというディレクトリが掘られ、その中にそのモジュールを構成するファイルがコピーされる。

* ファイルの編集

CVSの場合は、checkoutするとモジュールのコピーが作成され、各利用者はそれをいじることになる。保管庫のファイルを直接いじるわけではないので、どれほどめちゃめちゃにいじってもそれを登録しない限り、他人には迷惑をかけない。遠慮せずに好きなだけ改造しよう。

ファイルを改編するためのCVSコマンドは存在しない。使い慣れたエディタで編集すればよい。

* 他人が更新したモジュールを手元のコピーに反映させる

どんどん改造しよう、といっても、はじめのうちは先輩の改造を取り込むばかりで、自分ではなかなか直せないかもしれない。CVSに登録された更新を手元のコピーに反映させるには、そのモジュールのディレクトリ、先ほどの例では fluidlab/DMDFに移動し、次のようにする。

% cvs update

簡単ですね。ところでupdateをかける前に何が変更されたかを知りたければ、

% cvs diff

というコマンドを用いる。個人的には、

% cvs diff -u | less

のように-uオプションを指定して、unified diff形式で見るのが分かりやすいのでおすすめである。

* 自分が行った変更を保管庫に登録する

まず自分の行った変更を、保管庫に登録する必要があるかどうか、ちょっとだけ考えよう。プログラムなら、明白なバグがないか? コンパイルはちゃんと通るか? ファイルの追加・削除はちゃんとCVSに教えてあるか(下の節を参照)? などなど。いつでも元に戻せるから、さほど気にしなくともよいのだが、最低限の注意は怠らないようにしよう。

さて実際に変更を登録するには、モジュールのあるディレクトリに移動して、以下のコマンドを実行する。

% cvs commit

これによって、モジュールのコピーに対して行った全ての変更が、CVSの保管庫に登録される。

このとき自動的にエディタが開いて、変更点についてのコメントを求められるので、適切なコメントを入力する。コメントを保存してエディタを終了すれば、保管庫への登録が完了する。

* 個々のファイルの登録

変更が多岐にわたる場合は、上記の方法で登録すればよいが、あるファイルにちょっとした書き間違いが見つかって、そこだけ直した場合には、そのファイルだけを登録すればよい。

% cvs commit ファイル名

エディタが開いてコメントを求められることは、上と同じである。

* コメントをコマンドラインから指定する

コメントを入力するためにいちいちエディタが開くのが面倒だと感じるなら、次のようにコメントをコマンドラインから指定するとよい。

% cvs commit -m 'コメント' ファイル名

たとえば単に書き間違いを直しただけなら、-m 'Bug fix'のようにコメントを指定して登録するとよい。

* 競合があるとき

これまでさらっと流してきたが、実は登録はいつでも成功するとは限らない。自分の変更と他人の変更が競合したときは、CVSは文句を言って登録を中止する。具体的には、たとえば同じファイルをすでにAさんが変更していて、Bさんがそれに気づかずに変更をcommitしようとしたときに発生する。

% cvs commit redist.f
cvs commit: Up-to-date check failed for 'redist.f'
cvs [commit aborted]: correct above errors first!

[Under Construction] (未完成)

* ファイルの追加

ファイルを追加したい場合には、そのファイルを"cvs add"する。

% cvs add ファイル名

addしただけではCVS保管庫に反映されないことに注意。上に書いた"cvs commit"をしてはじめてファイルが保管庫に追加される。

ディレクトリを追加したいときも同じ。


% cvs add ディレクトリ名

このとき注意してほしいのは、そのディレクトリは追加されても、ディレクトリの中身は追加されないということ。追加したいファイルはひとつひとつcvs addしよう。

* バイナリファイルの追加

テキストファイルは上の方法でいいのだが、バイナリファイルを追加したいときにはバイナリであることを示すオプション-kbが必要となる。

% cvs add -kb バイナリファイル名

ウェブページをCVSで管理していて、画像ファイルなどを追加するときに、きっとこのオプションを使うだろう。

* ファイルの削除

ファイルやディレクトリを削除したいときには、まずそのファイルを削除してから"cvs remove"する。

% rm ファイル名
% cvs remove ファイル名

"remove"は"rm"あるいは "delete"でもよい。

前もってファイルを消しておくことに注意。これが面倒だったら、

% cvs remove -f ファイル名

のように-fオプションをつけてcvsを実行すると、ファイルを消してくれる。

ディレクトリの場合も同様だが、「ファイルの追加」と同じく、ディレクトリの中身までは自動で消してくれないので注意。

もし一度にたくさんのファイルやディレクトリを削除したければ、前もって不要となったファイルを全て消しておいた上で、

% cvs remove

のように引数なしで"cvs remove"を実行する。

この作業も「ファイルの追加」と同様、 "cvs commit"しないと保管庫には反映されない。

* 個人でバージョン管理する ― RCS

ファイルのバージョン管理は、うまく使うととても便利な道具である。CVSのように共同開発を支援するシステムだけでなく、個人で手軽に使えるシステムがほしければ、RCS(Revision Control System, See rcsintro(1)) が簡単に使えるのでおすすめである。

RCSを利用するには、次の節で述べるEmacsのバージョン管理コマンド(VC)から利用するのが簡単なので、著者はたいていこの方法を使っている。ちなみにこのHTMLファイルもEmacs経由でRCSで管理されている。

* RCSのマスターファイル用ディレクトリ

あるファイルのバージョン管理にRCSを利用するのであれば、そのファイルのあるディレクトリにRCSという名前のサブディレクトリを掘ることをおすすめします。そのディレクトリの中にマスターファイルが作られます。ディレクトリが無い場合には、作業ファイルと同じディレクトリにマスターファイルが作られるので動作上は問題ないのですが、どうもうっとうしいです。

* RCSの特徴

CVSとRCSは、とくに作業ファイルの扱いに違いがあります。CVSはファイルの集合をひとまとめにして扱います。作業の際には各自が保管庫のコピーを作成して、そのコピーを好きなようにいじるシステムです。

RCSは各ファイル単位でバージョン管理します。また「マスターファイル」 (CVSの保管庫に相当)から作られる「作業ファイル」はひとつだけで、複数人で共同開発する場合でも皆が同じファイルをいじることになります。したがって、ファイル変更の競合が起きないよう、作業する人はファイルを「ロック」して他人がいじれないようにし、編集作業を行います。編集作業が終わったら、変更点をマスターファイルに登録して、作業ファイルのロックを解除します。ロックを解除された作業ファイルは書き込み禁止になります。

まとめると、RCSで管理されているファイルは、ロック→編集→変更登録・アンロック→書き込み不可→ロック→…を繰り返すことになります。

この程度の知識を持っていれば、次の節を読んで、Emacsでバージョン管理ができるようになるでしょう。

* Emacsでバージョン管理する

Emacs/MuleにはCVSやRCSなどのバージョン管理システムと協調して、バージョン管理を行うコマンドがある。簡単に利用できるのでおすすめである。

詳しくはEmacsのinfoの中の"Version Control"という節を読んでもらうとして、ここではいちばん簡単なコマンドをひとつ説明する。

* 次に行うべき操作 ― C-x v v または C-x C-q

C-x v vまたはC-x C-qで、Emacsは「次に行うべき操作」をする。CVSの場合には次の通り。

利用しているバージョン管理システム(バックエンド)がRCSやSCCSの場合には、動作が異なる。これらのバージョン管理システムは作業ファイルをロックして他人が変更できないようにした上で、自分の変更を書き込むしくみになっている。

上記のようにたいていの作業はEmacsが適切に判断してくれるので、C-x C-qを覚えておくと、とっても幸せになれます。

* 参考

この節ではごく基本的な使い方だけを説明した。より詳しい使い方は、マニュアルや以下の参考文献、リンクを参照してほしい。


<- トップページ
工学院大学機械工学科流体研

リンクはご自由に。でもメールをくれると嬉しいな。

金野 祥久  konno@researchers.jp

Last modified: Wed Oct 4 10:07:16 JST 2000