RCS (Revision Control System) は大昔に使われていたバージョン管理システムだ。 21 世紀にもなって何で RCS なんかとも思うんだけど、恐竜が生きていた頃に作られたシステムの中には今でもファイルを RCS で管理しているものももしかすると残っていたりするかもしれない。 今回はその使い方を振り返っておく。
検証環境には CentOS7 を使った。
$ cat /etc/redhat-release CentOS Linux release 7.1.1503 (Core) $ uname -r 3.10.0-229.11.1.el7.x86_64
RCS をインストールする
RCS は yum を使ってインストールできる。
$ sudo yum -y install rcs
RCS を使ってみる
RCS を使うには、作業する場所に RCS という名前のディレクトリを作るのがセオリーになっている。
$ mkdir RCS
バージョン管理したいファイルを RCS に登録する
同じ場所に、バージョン管理したいファイルを書き出しておく。
$ cat << EOF > sample.txt /* \$Id\$ */ Hello, World EOF
この時点でのファイルの構成は以下のような感じ。
$ find . . ./RCS ./sample.txt
まずはバージョン管理したいファイルを ci コマンドで RCS に登録する。 説明を求められるので、ファイルの目的や変更内容について記述する。 入力を終えるには、新しい行で '.' (ピリオド) のみを入れて改行する。
$ ci -u sample.txt RCS/sample.txt,v <-- sample.txt enter description, terminated with single '.' or end of file: NOTE: This is NOT the log message! >> This is a sample file for training RCS >> . initial revision: 1.1 done
これで RCS にファイルが登録された。 すると、次のように RCS ディレクトリ以下に登録したファイルを管理するためのファイルができる。
$ find . . ./RCS ./RCS/sample.txt,v ./sample.txt
これは単なるテキストファイルになっているようだ。
$ file RCS/sample.txt,v RCS/sample.txt,v: ASCII text
内容を確認すると $Id$ のところが RCS によってバージョンなどを含む内容に置換されている。
$ cat sample.txt /* $Id: sample.txt,v 1.1 2015/08/25 13:47:37 vagrant Exp $ */ Hello, World
ちなみに ci コマンドが終わると、下手に編集できないようにファイルから書き込み権限が落ちる。
$ ls -l 合計 4 drwxrwxr-x 2 vagrant vagrant 25 8月 25 13:48 RCS -r--r--r-- 1 vagrant vagrant 75 8月 25 13:48 sample.txt
バージョン管理しているファイルを編集する
ファイルを編集するには、まず co コマンドでファイルに書き込み権限を付与する。
$ co -l sample.txt sample.txt,v --> sample.txt revision 1.1 (locked) done $ ls -l 合計 4 drwxrwxr-x 2 vagrant vagrant 25 8月 25 13:51 RCS -rw-r--r-- 1 vagrant vagrant 83 8月 25 13:51 sample.txt
ファイルを好きに編集する。
$ sed -i -e "s:World:RCS:g" sample.txt
変更内容を確認するには rcsdiff コマンドを使おう。
$ rcsdiff sample.txt =================================================================== RCS file: RCS/sample.txt,v retrieving revision 1.1 diff -r1.1 sample.txt 2c2 < Hello, World --- > Hello, RCS
ファイルの新しいバージョンを ci コマンドで登録する。 説明をまた聞かれるので変更内容を入力しておく。
$ ci -u sample.txt RCS/sample.txt,v <-- sample.txt new revision: 1.2; previous revision: 1.1 enter log message, terminated with single '.' or end of file: >> s:World:RCS:g >> . done
ちなみにオプションをたまに間違えるとファイルが消えて焦る
再び首尾よくファイルの編集までが終わったとする。
$ co -l sample.txt RCS/sample.txt,v --> sample.txt revision 1.2 (locked) done $ sed -i -e "s:Hello:Bye:g" sample.txt $ rcsdiff sample.txt =================================================================== RCS file: RCS/sample.txt,v retrieving revision 1.2 diff -r1.2 sample.txt 2c2 < Hello, RCS --- > Bye, RCS
ここで誤って ci コマンドに -u オプションを付け忘れると、どうなるだろうか。
$ ci sample.txt RCS/sample.txt,v <-- sample.txt new revision: 1.3; previous revision: 1.2 enter log message, terminated with single '.' or end of file: >> Good-bye RCS eternally >> . done
なんと、バージョン管理していたはずのファイルが消えてしまった。
$ ls RCS
とはいえ焦る必要はない。 実際にはバージョン管理システムに登録されたままなので co コマンドをオプションなしで実行すればすぐにファイルが復活する。
$ co sample.txt RCS/sample.txt,v --> sample.txt revision 1.3 done $ ls RCS sample.txt
どうせ ci コマンドと co コマンドは上記のオプションを付けて使うことしか無いので、こういったオペミスを防ぐためにオプションを付けた状態で alias を作っておいた方が良い気がする。
$ cat << EOF >> ~/.bashrc alias ci="ci -u" alias co="co -l" EOF
RCS ディレクトリがないとどうなる?
RCS ディレクトリを消した状態でファイルを登録してみよう。 ちなみに前述した通り RCS ディレクトリ以下にファイルの変更履歴が残っているので実際の環境では絶対に消さないように気をつけよう。
$ rm -rf RCS $ ci -u sample.txt sample.txt,v <-- sample.txt enter description, terminated with single '.' or end of file: NOTE: This is NOT the log message! >> . initial revision: 1.1 done
RCS ディレクトリが無い状況では同じディレクトリにバージョン管理用のファイルができることがわかる。 正直、邪魔だね。
$ ls sample.txt sample.txt,v
付録: RCS の代わりに Git を使ってみる
RCS は太古の昔に使われていたバージョン管理システムだし、ファイルのロック周りが煩雑だったりするので今から積極的に使う必要はないと思う。 代わりに Git で似たようなことをする方法について紹介しておく。
Git をインストールする
yum を使って Git をインストールする。
$ sudo yum -y install git
ファイルをコミットする際に必要なので、今のうちに Git の設定にユーザ名とメールアドレスを登録しておこう。
$ git config --global user.name "momijiame" $ git config --global user.email "momijiame@example.jp"
Git のリポジトリを作る
変更内容を保存するためのディレクトリ (リポジトリ) を作る。
$ mkdir repo
$ cd repo
リポジトリを初期化する。
$ git --bare init --shared
Initialized empty shared Git repository in /home/vagrant/work/repo/
必要なファイルが幾つか作られるので場所をメモっておこう。
$ ls
HEAD branches config description hooks info objects refs
$ pwd
/home/vagrant/work/repo
ホストが SSH でログインできる状態にあることを確認しておく。
$ ss -ant | grep :22 LISTEN 0 128 *:22 *:* ESTAB 0 0 10.0.2.15:22 10.0.2.2:59756 LISTEN 0 128 :::22 :::* $ systemctl status sshd sshd.service - OpenSSH server daemon Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled) Active: active (running) since 火 2015-08-25 13:45:14 UTC; 19min ago Main PID: 1086 (sshd) CGroup: /system.slice/sshd.service └─1086 /usr/sbin/sshd -D
Git のリポジトリをチェックアウトする
リモートにある (といってもローカルホストの) リポジトリを手元にチェックアウトしてくる。
$ cd /var/tmp $ git clone localhost:/home/vagrant/work/repo Cloning into 'repo'... The authenticity of host 'localhost (::1)' can't be established. ECDSA key fingerprint is 0e:ae:85:dc:52:d7:70:4d:fd:6f:9a:f7:0c:2f:a9:99. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'localhost' (ECDSA) to the list of known hosts. vagrant@localhost's password: warning: You appear to have cloned an empty repository. $ ls | grep repo repo
バージョン管理したいファイルを保存する。
$ cd repo $ cat << EOF > sample.txt Hello, World EOF
変更内容をコミットしたらリモートリポジトリにプッシュする。 これで Git のリモートリポジトリにファイルが登録された。
$ git add sample.txt $ git commit -m "This is a sample file for training Git" $ git push origin master Counting objects: 3, done. Writing objects: 100% (3/3), 256 bytes | 0 bytes/s, done. Total 3 (delta 0), reused 0 (delta 0) To localhost:/home/vagrant/work/repo * [new branch] master -> master
リモートリポジトリにファイルとその変更履歴は全て残っているので、あとはローカルのリポジトリを削除してしまってもチェックアウトしなおせばすぐに復元できる。
$ cd .. $ rm -rf repo/ $ git clone localhost:/home/vagrant/work/repo Cloning into 'repo'... remote: Counting objects: 3, done. remote: Total 3 (delta 0), reused 0 (delta 0) Receiving objects: 100% (3/3), done. $ cat repo/sample.txt Hello, World
ばっちり。
まとめ
今回は太古の昔に使われていたバージョン管理システムの RCS の使い方について振り返ってみた。 そして、同じことを現代のバージョン管理システムであるところの Git を使ってやる方法について書いた。