RCS 邪級講座

-- You may never wanted to do this.

[RCS超入門] [RCS中級講座] [RCS上級講座] [RCS邪級講座]

正直に ci / co していけば何も問題は起こらないんですが、 一人で色々いじっているともっと変な要求も出てきます。

「そんなことは不可能ぢゃ」て場合もありますが、 以下のような変則技も可能といえば可能です。

$Id: rcs9.html,v 1.18 2003/12/14 20:29:03 kabe Exp $


別のディレクトリに取り出す

% co ../../src/RCS/main.c,v

要するに RCS管理ファイルだけを指定 した場合は、 カレントディレクトリにそのファイルが展開されます。

この方法を使えば RCS が想定している

になるんですが、このままではいかんせん指定がめんどくさい。

ので、ファイル一個・一回こっきりであれば直接指定でもいいでしょうけど、 違う場所で作業を続行していくのであれば、 作業場所/RCS/ をオリジナルの RCS/ へのシンボリックリンクにします。 こうすれば co main.c で直接取り出せる。

▽考察

ただ、 単一ファイルのロック競合は RCS が管理してくれますが、 「オレは1.1.1枝、アイツは1.1.2枝」とか、hello.c と hello.1 の 整合性維持なんてのは RCS ではやってくれません。

また、 ディレクトリが複数あったりすると、 全部のディレクトリに RCS/ のリンクを作らねばならんので結構手間がかかるし、 オリジナルの RCS/ (まさに「リポジトリ」) が移動したなんて時には 大騒ぎです。

ので、本気で複数{ディレクトリ・ファイル・版}を扱うようになったら CVS あたりにステップアップしましょう。そのころには RCS の限界が わかっているので、CVS がありがたく感じられるはず。


別の名前の作業ファイルを登録

別のファイル名で取り出す などで、登録されているファイル名と別の名前で作業を行なっていても、 いずれは登録したくなります。どうしましょ。

方法1.一瞬だけ入れ換えてci

	% mv tmp.cgi script.cgi		# 上書き!
	% ci -u script.cgi		# 素早く登録
ci が終了するまでは一時的に script.cgi が使えない状態になるかもしれません。 終了すれば、暗黙の co によって mode は戻ります。 →File Modeについて

方法2.とにかく名前だけ揃えてci

	% mkdir temp				# 作業場所確保
	% mv tmp.cgi temp/script.cgi		# 名前を揃える
	% ci temp/script.cgi RCS/script.cgi,v	# 両方指定して登録
ci や co では、作業ファイルと管理ファイルを両方指定すると、 それらに対して登録作業を行なってくれます。 ファイル名が揃っていないと関連のない別のファイルだと思われるので、 "ci tmp.cgi RCS/script.cgi,v" などとやっても無駄です。
こんな手間をかけるんなら、最初から違うディレクトリで 作業すればよろしい。 これを自動化してくれるのが CVS …だと思う →別のディレクトリに取り出す


すでに何個かの版があるファイルをRCS化する

古いファイルの名前を一旦通常の名前に変更してから、 ci で一つずつ登録していく。その際、-d -w で 変更時間や変更者を指定して登録する。

ツボ: ci [-ddate] [-wlogin]

例として、

が転がっているとしましょう。

▽1) まず最新版を退避。

ci は標準入力からファイルを流し込んで登録 といったことができないため、「正しいファイル名」を 空けておく必要があります。
	% mv expire.ctl{,-}	(退避 )
	

▽2) ソース展開時(.orig)のものを登録する。

	% mv expire.ctl{.orig,}	(正しい名前にして )
	% ci -l expire.ctl	(登録。)
	
基本的にはこれでいいんですが、更新日時は「現在」になります。 もとのファイルに RCSマーカーが入っている場合は
	% ci -l -k expire.ctl	(RCSマーカー自動判別 )
	
とすると、作者名や版番号を探しだして勝手につけてくれます。

▽3) 次の版を登録する。

	% rm expire.ctl
	% cp -p expire.ctl{.19970518,}	(変更時刻を保存 )
	% rcsdiff expire.ctl		(コメントは何を書こうか)
	% ci -l1.8.1 -wjawas -d expire.ctl	(作成者を明示して登録)
	
修正者として記録したいのは「私」ではないので、-w オプションで明示的に作者名を渡します。 更新時刻は何もしないと「現在」になるので、-dで ファイルの修正時刻を拾います。 修正時刻が信用ならん場合は -d"1997/05/18 12:34:56" と明示します。

ここでは、もとのファイルにすでに"Revision: 1.8" がついていたので、 修正したファイルは自動的につく1.9 ではなく、 枝1.8.1.* を陽に指定して登録してみました。

▽3') デフォルト枝を 1.8.1.* に設定する。

	% rcs -b1.8.1 expire.ctl	(デフォルト枝変更)
	
枝を作ったら、これをやっとかないと次の ci/co で幹に戻ってしまいます。

▽4) 次の版を登録する

デフォルト枝を指定しておけば、以後の版番号の生成はciに任せてよい。
	% rm expire.ctl
	% cp -p expire.ctl{.19970717,}
	% ci -l -wkabe -d1997/07/17 expire.ctl
	

▽5) 最新版を登録して終了

	% rm expire.ctl
	% mv expire.ctl{-,}
	% ci -u -wlabria expire.ctl
	

▽*)「RCSにしたよ」とアナウンスする

一応啓蒙しておかないと、また expire.ctl.19970731 とかいった ファイルを作る人がいるかもしれません。 くだらんけど意外に重要。

人様のソースを再登録する

	% ident srvrsmtp.c
	srvrsmtp.c:
	     $Id: srvrsmtp.c,v 8.471.2.2.2.67 2001/01/07 19:31:05 gshapiro Exp $
	     $Id: srvrsmtp.c,v 8.471.2.2.2.67 2001/01/07 19:31:05 gshapiro Exp $
	% ci -k srvrsmtp.c
	RCS/srvrsmtp.c,v  <--  srvrsmtp.c
	ci: RCS/srvrsmtp.c,v: Branch point doesn't exist for revision 8.471.2.2.2.67.

他人のソースをもらってきて ちょこっと改造、てな時には RCS管理ファイルがない状態からはじまるわけで、 作者と揃えようと -k で既存の版番を拾おうとすると 「そんな枝はねぇ」と怒られる。 (例は根本(branch point)の 8.471.2.2 がないという意味)

しょうがないので ci -u8.471, ci -f8.471.2.2 などとして枝を 定義してくわけですが、 co -r8.471.2.2.2.67 とオリジナルを取り出したときに $Id$ が元に戻らず「現在時刻」「自分のid」だと多少ヘコむので 慎重にいきます。

念のためバックアップをとっておきます。ci -u では暗黙の co で $Id$ が書き替るので、失敗したときに本当に戻せなくなります。

	% cp -p srvrsmtp.c srvrsmtp.c.orig

まず幹を登録。いきなり8.471から登録できます。 -k (既存Id拾う) を抜かすと「自分」で登録されてしまうので注意。

	% ident srvrsmtp.c
	srvrsmtp.c:
	     $Id: srvrsmtp.c,v 8.471.2.2.2.67 2001/01/07 19:31:05 gshapiro Exp $
	     $Id: srvrsmtp.c,v 8.471.2.2.2.67 2001/01/07 19:31:05 gshapiro Exp $
	% ci -k -u -r8.471 srvrsmtp.c	# 既存Id拾う、残す、版番明示
	srvrsmtp.c,v  <--  srvrsmtp.c
	enter description, terminated with single '.' or end of file:
	NOTE: This is NOT the log message!
	>> srvrsmtp.c
	>> .
	initial revision: 8.471
	done

枝を生やしていく。 内容を変更せずに登録していくので -f (強制登録) も必要。

	% ci -k -u -f -r8.471.2.2 srvrsmtp.c	# 拾う、残す、強制
	srvrsmtp.c,v  <--  srvrsmtp.c
	new revision: 8.471.2.2; previous revision: 8.471
	done
	% ci -k -u -f -r8.471.2.2.2.67 srvrsmtp.c
	srvrsmtp.c,v  <--  srvrsmtp.c
	new revision: 8.471.2.2.2.67; previous revision: 8.471.2.2
	done

お好みでデフォルト枝も変更。 何もしなければ 幹 (8.471) になります。

	% rcs -b8.471.2.2.2.67 srvrsmtp.c
	RCS file: srvrsmtp.c,v
	done

RCSINIT環境変数のぐあいでは、co で取り出しても完全には戻りません。 まあ意味は同じですから気にせんでもいいかもしれませんが

co -kb とすれば、co時のラベル置換が 行われなくなるので完全に戻る…はず…です。
	% co -M -r8.471.2.2.2.67 srvrsmtp.c	# mtime保存
	% diff srvrsmtp.c.orig srvrsmtp.c
	19c19
	< static char id[] = "@(#)$Id: srvrsmtp.c,v 8.471.2.2.2.67 2001/01/07 19:31:05 gshapiro Exp $ (with SMTP)";
	---
	> static char id[] = "@(#)$Id: srvrsmtp.c,v 8.471.2.2.2.67 2001-01-08 04:31:05+09 gshapiro Exp $ (with SMTP)";
	21c21
	< static char id[] = "@(#)$Id: srvrsmtp.c,v 8.471.2.2.2.67 2001/01/07 19:31:05 gshapiro Exp $ (without SMTP)";
	---
	> static char id[] = "@(#)$Id: srvrsmtp.c,v 8.471.2.2.2.67 2001-01-08 04:31:05+09 gshapiro Exp $ (without SMTP)";
"@(#)" てのは SCCSマーカーですな。 ident だけでなく what でも$Id$ を取り出せる。

元の置換キーワードを復元する

外部由来の $Id$ がたくさんついているようなファイル

	$Id: use_cw_file.m4,v 8.9 1999/02/07 07:26:13 gshapiro Exp $
	$Id: proto.m4,v 8.446.2.5.2.38 2000/12/28 03:37:28 ca Exp $
	$Id: local.m4,v 8.50.16.2 2000/09/17 17:04:22 gshapiro Exp $
	$Id: smtp.m4,v 8.56.2.1.2.3 2000/09/25 13:53:27 ca Exp $
を登録してから取り出すと、置換が全部に対して行われて
	$Id: sendmail.cf,v 1.1 2002-02-06 15:16:59+09 root Exp $
	$Id: sendmail.cf,v 1.1 2002-02-06 15:16:59+09 root Exp $
	$Id: sendmail.cf,v 1.1 2002-02-06 15:16:59+09 root Exp $
	$Id: sendmail.cf,v 1.1 2002-02-06 15:16:59+09 root Exp $
となるのはかなり悲しい (本来は生成元の各ファイルをいじるのが正しい…) ので、元に戻したい場合は
	% co -kb sendmail.cf

$Id$ の置換は あくまで co 取り出し時に行われるだけで、 登録時は置換が行われる前の状態で登録されるので、 「置換すんな」と言うだけで戻すことができます。

もちろん、いったん -kb をつけずに取り出したものをいじって登録して しまったら最後、 全部 $Id: sendmail.cf,v ... になってしまうので、 くれぐれも用心すること。

変えたくない $Id$ は、さっさと別の文字列に変えてしまうほうが簡単。 (最初からそう言え <いやいや、初回登録はオリジナルのままでやりたいとかあるっしょ)

変更の一部分だけ登録する

・まっとうな方法 ・まっとうでない方法

最新版の上書き

ciしたあと、「あ、あそこも変更しとけば良かった…」と思うことも 結構あります。一般的ではないのですが、最新版に関してなら 上書きすることも可能です。

でも素直にもう一度 ci して新しいバージョン番号をもらったほうが めんどくさくなくていいです。 番号が増えるのがいやなら枝を生やせばよろしい。

% rcs -u file
まずロックを外す。ロックがかかっていると版の消去はできません。
% rcs -o1.2 file # 最新版が1.2の場合
RCSファイルから最新版を消す。バージョン番号は明示が必要。
% rcs -l file
一つ前の版に対しロックがかかっているように見せかける。
登録したかったものを用意。
そこに転がっている作業ファイルを chmod +w して再編集します。 うかつに co すると「一つ前の版」になってしまうので注意。
% ci -u file
変更後のものを登録する。さっき消したバージョン番号がつく。

RCS/ 以下にも同名ファイルがあったりして

初回登録時に

	% ci -u .htaccess
	ci: RCS/.htaccess:1: missing 'head' keyword
	ci aborted
いきなりこんなエラーを食らうと「は?」という感じですが、 要するにすでに存在している RCS/.htaccess が RCS管理ファイルだと 思われているわけです。

こういうひねくれた状況にはなかなか遭遇しないと思いますが (それこそ .htaccess くらいだろうな〜) 遭遇してしまった場合は、 作業ファイルと管理ファイルの両方を明示的に指定します。

	% ci -u .htaccess RCS/.htaccess,v
	RCS/.htaccess,v  <--  .htaccess
	enter description, terminated with single '.' or end of file:
	NOTE: This is NOT the log message!
	>>
実はこの場合なら管理ファイルだけの指定 (ci -u RCS/.htaccess,v) でもちゃんと動きますが、この期に及んで限界を攻めるのは あまりやらんほうがいいのではないかと…


かべ@sra-tohoku.co.jp