RCS を 使うことで /etc/* や .cshrc、プログラムのソースコードなどの テ
キストファイルの 履歴管理を行なうことができます。

また RCS は 複数のユーザーの 同一ファイルへの変更を調停し、だれが いつ 
どこを なんのために変更したのかを記録してくれます。

★ 入手方法

% rcs
rcs error: No input file
...
%

とか 言われれば すぐに使えます。

ftp サイトから ソースをダウンロードして コンパイルするのが 王道ですが…

★ 基本的な履歴管理

ここでは foo.txt というファイルを 変更しながら、RCS を 使ってみます。
てきとうな ディレクトリに foo.txt というファイルをつくってみます。

% vi foo.txt
% cat foo.txt
昨日キャベツを買いました。
%

では、これを RCS 管理しましょう。 RCS では 変更履歴や過去のバージョン
は すべて "RCSファイル" に 格納されます。 RCSファイルは もとのファイル
名に ,v が 追加されたものです。 この場合は foo.txt,v と なります。
"RCS" という 名前のディレクトリを作っておくと 自動的にそこに RCS ファ
イルを格納してくれます。 RCS という名前のディレクトリを作っておきましょ
う。

% mkdir RCS

いよいよ foo.txt を RCS 管理します。 新しいファイルの管理を始めたり、
変更が一段落 したときには "チェックイン" します。

% ci -u foo.txt
foo.txt,v  <--  foo.txt
enter description, terminated with single '.' or end of file:
NOTE: This is NOT the log message!
>> 

ファイルの説明を求められています。 入れてみましょう。

>> RCS の 練習用ファイルです。
>> .
initial revision: 1.1
done
% 

RCS ディレクトリを覗いてみると…

% ls RCS
foo.txt,v
% 

これが RCSファイルです。

もとのファイルはどうなったでしょうか?

% ls -l foo.txt
-r--r--r--  1 sakauchi  peck  27 Apr 17 20:53 foo.txt
% 

あれ? リードオンリーになってますね。
チェックインしたファイルは、誰も編集できなくなるのです。
これを 修正するには、まず “チェックアウト”してください。

% co -l foo.txt
RCS/foo.txt,v  -->  foo.txt
revision 1.1 (locked)
done
% ls -l foo.txt
-rw-r--r--  1 sakauchi  peck  27 Apr 17 21:00 foo.txt
% 

# ここで、もし チェックアウトしたのが sakauchi さんじゃなくて、
# kwatanab さんだと…
# -rw-r--r--  1 kwatanab  peck  27 Apr 17 21:00 foo.txt
# と なるはずです。
# つまり 『ロックした本人しか 直せない!』 ということです。
# こうして 同じファイルを二人の人が編集することを防いでいます。
# ちなみに すでに誰かがロックしているファイルをロックしようとすると…
#
# % co -l foo.txt
# RCS/foo.txt,v --> foo.txt
# co: RCS/foo.txt,v : Revision 1.1 is already locked by kwatanab.
#
# とつれなく言われてしまいます。

次に、foo.txt を 修正しましょう。

% vi foo.txt
% cat foo.txt
昨日キャベツを買いました。
なかに虫がはいっていました。
%

また チェックイン です。

% ci -u foo.txt
RCS/foo.txt,v  <--  foo.txt
new revision: 1.2; previous revision: 1.1
enter log message, terminated with single '.' or end of file:
>> 虫のことを追加。
>> .
done
% 

こんどは『ログメッセージを入れてね』と 言ってることに注意して下さい。

またまた 修正して…

% co -l foo.txt
RCS/foo.txt,v --> foo.txt
revesion 1.2 (locked)
% vi foo.txt
% cat foo.txt
昨日キャベツを買いました。
なかに虫がはいっていました。
とっても大きな虫で、思わずたじろぎました。
% ci -u foo.txt
RCS/foo.txt,v  <--  foo.txt
new revision: 1.3; previous revision: 1.2
enter log message, terminated with single '.' or end of file:
>> もっと虫のこと。
>> .
done
% 

# 普段の作業は、この3つのコマンドをセットで使うことが多いのです。
# もちろん vi は 愛用のエディタにおきかわりますが。

リビジョン番号が 1.1 -> 1.2 -> 1.3 と 変わっていきますね?
1.9 の 次は 1.10 に なります。
リビジョン 2 に するには ci -r2 foo.txt と します。
リビジョンは 2.1 に なります。

さてさて、では いろいろとやってみましょう。

まずは 履歴の一覧を 見ましょう。

% rlog foo.txt

RCS file: RCS/foo.txt,v
Working file: foo.txt
head: 1.3
branch:
locks: strict
access list:
symbolic names:
keyword substitution: kv
total revisions: 3;	selected revisions: 3
description:
RCS の 練習用ファイルです。
----------------------------
revision 1.3
date: 1997/04/17 12:19:29;  author: sakauchi;  state: Exp;  lines: +1 -0
もっと虫のこと。
----------------------------
revision 1.2
date: 1997/04/17 12:13:05;  author: sakauchi;  state: Exp;  lines: +1 -0
虫のことを追加。
----------------------------
revision 1.1
date: 1997/04/17 11:53:58;  author: sakauchi;  state: Exp;
Initial revision
----------------------------
=============================================================================
% 

とっても便利そうでしょ?
# ウチじゃ 職場の人間関係も改善されるました。 :p

では revision 1.1 と revision 1.2 の 間で なにを具体的に変更したのか確
認してみましょう。

% rcsdiff -c -r1.1 -r1.2 foo.txt
===================================================================
RCS file: RCS/foo.txt,v
retrieving revision 1.1
retrieving revision 1.2
diff -c -r1.1 -r1.2
*** foo.txt	1997/04/17 11:53:58	1.1
--- foo.txt	1997/04/17 12:13:05	1.2
***************
*** 1 ****
--- 1,4 ----
  昨日キャベツを買いました。
+ なかに虫がはいっていました。
%

# オプション c は diff の オプションです。

ほらぁ、とっても便利そうでしょ?

では 最初のリビジョンを取り出してみましょう。
修正するわけではないので l オプション (lock オプション) はつけません。

% co -r1.1 foo.txt
RCS/foo.txt,v  -->  foo.txt
revision 1.1
done
% cat foo.txt
昨日キャベツを買いました。
% 

ほら、『あの日に帰りたい♪』 って 泣くことはもうありません。
帰れるんだもん。

最新版に戻すときは…

% co foo.txt
RCS/foo.txt,v  -->  foo.txt
revision 1.3
done
% 

これで OK です。

★ ファイルへのリビジョン情報の埋め込み

もう一つやってみましょう。

co -l foo.txt
% RCS/foo.txt,v  -->  foo.txt
revision 1.3 (locked)
done
% vi foo.txt
% cat foo.txt
$Header$

昨日キャベツを買いました。
なかに虫がはいっていました。
とっても大きな虫で、思わずたじろぎました。
% ci -u foo.txt
RCS/foo.txt,v  <--  foo.txt
new revision: 1.4; previous revision: 1.3
enter log message, terminated with single '.' or end of file:
>> キーワードを追加
>> .
done
% 

さておたちあい。 foo.txt を もう一度 cat してみると…

% cat foo.txt
$Header: /home/sakauchi/RCS/foo.txt,v 1.4 1998/04/02 05:59:30 sakauchi Exp sakauchi $

昨日キャベツを買いました。
なかに虫がはいっていました。
とっても大きな虫で、思わずたじろぎました。
% 

というわけです。キーワードには
$Author$
$Date$
$Header$
$Id$
$Locker$
$Log$
$Name$
$RCSfile$
$Revision$
$Source$
$State$
があります。

これがどんなに便利かというと…

% cat main.c
static char rcsid[] = "$Header$";

extern void sub( void );

int main( int argc, char **argv )
{
    sub();
    return ( 0 );
}    


% cat sub.c
static char rcsid[] = "$Header$";

#include <stdio.h>

void sub( void )
{
    printf( "あたしって 可愛い?\n" );
}
% ci -u main.c sub.c
RCS/main.c,v  <--  main.c
enter description, terminated with single '.' or end of file:
NOTE: This is NOT the log message!
>> エントリルーチン
>> .
initial revision: 1.1
done
RCS/sub.c,v  <--  sub.c
enter description, terminated with single '.' or end of file:
NOTE: This is NOT the log message!
>> メッセージ表示ルーチン
>> .
initial revision: 1.1
done
% gcc -o foo main.c sub.c
% ./foo
あたしって 可愛い?
% ident foo
foo:
     $Header: /home/sakauchi/sample/main.c,v 1.1 1998/04/02 05:42:30 sakauchi Exp sakauchi $
     $Header: /home/sakauchi/sample/main.c,v 1.1 1998/04/02 05:42:45 sakauchi Exp sakauchi $
% 


ident というコマンドは RCS キーワード文字列を ファイルの中から抽出して
くれます。 だから こういう仕掛けをして プログラムをつくれば、バイナリ
からそれぞれの モジュールの リビジョンを表示してくれる… というわけで
す。

★ ケーススタディ:ロックしたまま出張に行っちゃった!

% co -l foo.txt
RCS/foo.txt,v  -->  foo.txt
co: RCS/foo.txt,v: Revision 1.4 is already locked by kwatanab.
% 

で! けいこさんたら、さっき走ってどっか行っちゃった… ;_;
しかたがない…

まずは けいこさんの修正中ファイルを退避しておきます。

% mv foo.txt foo.txt.kwatanab

けいこさんの ロックを破ります。

% rcs -u foo.txt
RCS file: RCS/foo.txt,v
Revision 1.4 is already locked by onagi.
Do you want to break the lock? [ny](n): y
State the reason for breaking the lock:
(terminate with single '.' or end of file)
>> Sorry, But Dr.Cherry said to me "Soon, add my student account."
>> And you've gone... So I break your lock.
>> Your work file is saved as foo.txt.kwatanab.
>>
>> Thank you.
>> Atushi.
>> .
1.4 unlocked
done
% 

入力したメッセージは E-Mail で 本人に送られます。
素の mail コマンドで 日本語メールが送信できる環境であれば、
日本語で入力しても もちろんかまいません。

これで、チェックアウトできるはずです。

% co -l foo.txt
RCS/foo.txt,v  -->  foo.txt
revision 1.4 (locked)
done
% 

★ ケーススタディ:Windows の .ini ファイル

Windows の .ini ファイルも RCS 管理してました。
ずいぶん幸せになりました。
ただ、ci -u すると read only に なっちゃうのは困りものです。
(プログラムも書き換えますからね)
そもそも、『ロックしなきゃ直せない』っていうのは マルチユーザーのシス
テム以外では不要です。

RCS は こういうモードもサポートしています。今まで説明してきたモードを
ストリクトモードといいます。
ci -u しても、リードオンリーにならず、ロックしていなくても どんどんチェッ
クインできるモードを ノン・ストリクトモードといいます。

% rcs -L <file>		ストリクトモードにする
% rcs -U <file>		ノン・ストリクトモードにする

デフォルトのモードは、コンパイル時に決められます。

★ ブランチ

RCS では 1.1 -> 1.2 -> 1.3 という 『幹』の他に

    1.2  -> 1.2.1.1 -> 1.2.1.2 -> 1.2.1.3 ..

という 『枝(ブランチ)』を 作ることも可能です。 シンボリック・リンク
で RCS ディレクトリを 共有して、ブランチすることで 新機能のテストと 従
来バージョンのメンテナンスを並行しておこない、最終的に成果をマージする
こともできます。

ローカルドライブでの開発を禁止して、これを使うことで『このバクは、いつ
かきたバグ』という不幸はなくなりました。

★ RCS の 限界と その他のソフトウェア

複数のディレクトリからなるような 大規模なシステムに対しては RCSの フロ
ントエンドとして CVS というソフトウェアがあります。FreeBSD プロジェク
トのすべてが これで管理されています。

RCS は diff に 依存していますから ( RCSファイルには差分のみ格納されま
す)バイナリファイルを扱うことができません。
Delphi2 には バイナリファイルも 扱えるように 拡張された PVCS というシ
ステムが組み込まれています。

★ まとめ

いろいろ書きましたけど… 

RCS ディレクトリをつくって、変更する前に co -l 変更したら ci -u するだ
けで 幸せになれると 思います。

昔から愛用しているツールの代表格ですね。