ペグ・リビジョンと操作対象リビジョン

リビジョン番号の指定に-rを使う場合と@を使う場合だと、意味が異なるんだよ!

そんなことを今更知ったSubversion歴3年のエンジニアです。

どういうことかといいますと。

あるファイルを削除して、同じ名前の別ファイルを追加したケースを考えるわけだよ。

$ svn st -v
                1        1 idesaku      .
                1        1 idesaku      HOGE.txt
$ svn remove HOGE.txt
$ svn ci (ここでrev.2)
$ echo hogehoge > HOGE.txt
$ svn add HOGE.txt
$ svn ci (ここでrev.3)

で、あるときrev.1のHOGE.txtの中身を見たくなったとする。このとき、次のようにコマンドを実行すると、見ることができない。

$ svn cat -r1 HOGE.txt
svn: 'HOGE.txt' (リビジョン 1) のリポジトリの位置が見つかりません
$

こうなるのは、rev.3のHOGE.txtとrev.1のHOGE.txtが、名前が同じなだけで別物であることをSubversionリポジトリが理解しているからである。rev.3で新たに追加されたHOGE.txtは、rev.1のころは存在していなかった。存在しなかったものは読めない。なるほど。

そして、別ファイルでもなんでもいいから、rev.1時点でHOGE.txtという名前だったファイルを見たい、という今回のようなケースでは、このようにコマンドを叩く。

$ svn cat HOGE.txt@1
Stay alert!! Trust no one!! Keep your laser handy!!
$

あってる。

オプション-rで指定するリビジョン番号は「操作対象リビジョン」という。これに対して、@で指定するリビジョンは「ペグ・リビジョン」という。両者の違いは、ファイルパスとリビジョン番号の解決順にある。

「操作対象リビジョン」は、まずファイルパスを解決し、そのあとリビジョン番号を解決する。つまり、「HOGE.txtのrev.1」という指定になる。上記の例では先に新しいHOGE.txtのみを処理対象として特定するから、別物であるrev.1のHOGE.txtを取得できない。

これとは逆に、「ペグ・リビジョン」では先にリビジョン番号を解決し、その後ファイルパスを解決する。「rev.1のHOGE.txt」という指定をするのである。最初に指定リビジョン時のツリーを特定し、そのときに存在したファイルパスを取る、という順序で処理が進むので、別物だが同じ名前であるrev.1のHOGE.txtを無事取得できる。

この2つは同時に指定することも可能。

$ svn cat -r1 HOGE.txt@3

この場合、まずペグ・リビジョン、続けて操作対象リビジョンの順で解決する。つまり、まずはrev.3時点のHOGE.txtを引っ張り出し、これの履歴をrev.1まで遡っていく。

・・・そんなことがSubversion Bookに書いてありましたよ(間違ってないよな?)。おかしいなぁ、ここ読んだ覚えがあるんだが。読んだだけじゃダメですねそうですね。

置換前のファイルにアクセスできないことは、Subversionに対して感じていた数少ない不満の一つだったが、単に自分が無知なだけでございました。すまん、Subversion開発チームの皆様方。あんたらにスキは無かった。