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

We copy, move, rename, and completely replace files and directories on our computers all the time. And your version control system shouldn't get in the way of your doing these things with your version-controlled files and directories, either. Subversion's file management support is quite liberating, affording almost as much flexibility for versioned files as you'd expect when manipulating your unversioned ones. But that flexibility means that across the lifetime of your repository, a given versioned object might have many paths, and a given path might represent several entirely different versioned objects. And this introduces a certain level of complexity to your interactions with those paths and objects.

Subversion is pretty smart about noticing when an object's version history includes such 「changes of address」. For example, if you ask for the revision history log of a particular file that was renamed last week, Subversion happily provides all those logs—the revision in which the rename itself happened, plus the logs of relevant revisions both before and after that rename. So, most of the time, you don't even have to think about such things. But occasionally, Subversion needs your help to clear up ambiguities.

The simplest example of this occurs when a directory or file is deleted from version control, and then a new directory or file is created with the same name and added to version control. Clearly the thing you deleted and the thing you later added aren't the same thing. They merely happen to have had the same path, /trunk/object for example. What, then, does it mean to ask Subversion about the history of /trunk/object? Are you asking about the thing currently at that location, or the old thing you deleted from that location? Are you asking about the operations that have happened to all the objects that have ever lived at that path? Clearly, Subversion needs a hint about what you really want.

And thanks to moves, versioned object history can get far more twisted than that, even. For example, you might have a directory named concept, containing some nascent software project you've been toying with. Eventually, though, that project matures to the point that the idea seems to actually have some wings, so you do the unthinkable and decide to give the project a name. [18] Let's say you called your software Frabnaggilywort. At this point, it makes sense to rename the directory to reflect the project's new name, so concept is renamed to frabnaggilywort. Life goes on, Frabnaggilywort releases a 1.0 version, and is downloaded and used daily by hordes of people aiming to improve their lives.

いい話しです。まったく。しかしこれで話しが終わるわけではありません。あ なたは企業家です。すでに次の着想を得ています。あなたは新しいディレクト リconcept を作り、次の開発サイクルが始まります。 実際にはこのサイクルは何年にもわたって何度も繰り返し発生します。いつも conceptディレクトリから始め、時にはそのアイディア を膨らませるためにディレクトリの名称は変更され、時にはそのアイディアを ボツにするためにディレクトリは削除されます。あるいは、さらにややこしい 場合、いったん concept を別の名前に変えた後、何か 理由があって再びconcept に名前を戻したりすること もあるでしょう。

In scenarios like these, attempting to instruct Subversion to work with these re-used paths can be a little like instructing a motorist in Chicago's West Suburbs to drive east down Roosevelt Road and turn left onto Main Street. In a mere twenty minutes, you can cross 「Main Street」 in Wheaton, Glen Ellyn, and Lombard. And no, they aren't the same street. Our motorist—and our Subversion—need a little more detail in order to do the right thing.

In version 1.1, Subversion introduced a way for you to tell it exactly which Main Street you meant. It's called the peg revision, and it is a revision provided to Subversion for the sole purpose of identifying a unique line of history. Because at most one versioned object may occupy a path at any given time—or, more precisely, in any one revision—the combination of a path and a peg revision is all that is needed to refer to a specific line of history. Peg revisions are specified to the Subversion command-line client using at syntax, so called because the syntax involves appending an 「at sign」 (@) and the peg revision to the end of the path with which the revision is associated.

ではこの本の中でいつも出てくる --revision (-r)で指定 されるほうのリビジョンは何と言われるのでしょうか ? こちらは 操作対象リビジョン(あるいはリビジョンの範囲を指定する場合 には、操作対象リビジョン範囲) と呼ばれます。いっ たん特定の履歴ラインがパス名とペグ・リビジョンによって指定されると Subversion は操作対象リビジョンに対して要求された操作を実行します。 この話をシカゴの道順のたとえで説明すると、 606 N. Main Street in Wheaton に行きたい場合だと [19]Main Street」がパス名に、「Wheaton」がペグリビ ジョンにあたるものと考えることができます。この二つの情報によって実際に 行ってほしい道順(メインストリートの北、あるいは南)を特定することができ、 行き先を探すのに、間違った別のメインストリートを右往左往せずにすみます。 そして、操作対象リビジョンにあたる 「606 N.」 によって実際 に行きたい場所を正確に知ることができるというわけ です。

ずっと以前に作っておいたリポジトリがあって、リビジョン 1 で最初の conceptディレクトリとその中にある IDEAという名前のファイルを追加したとしましょう。 このファイルは実際のコンセプトについての説明が書いてあります。 実際のソースコードを追加したり修正したりしてたくさんのリビジョンが 追加されたあと、リビジョン 20 でこのディレクトリを frabnaggilywortに名称変更したとしましょう。 リビジョン 27 で新しい着想を得たので、新規にconcept ディレクトリを作り、またその中に新規に IDEA ファイルを置いて、その内容を書いておきます。そして良くできたロマンス 小説よろしくその後 5 年間で 20,000 リビジョンにまで達したと しましょう。

Now, years later, we wonder what the IDEA file looked like back in revision 1. But Subversion needs to know if we are asking about how the current file looked back in revision 1, or if we are asking for the contents of whatever file lived at concepts/IDEA in revision 1. Certainly those questions have different answers, and because of peg revisions, you can ask either of them. To find out how the current IDEA file looked in that old revision, you run:

$ svn cat -r 1 concept/IDEA 
svn: Unable to find repository location for 'concept/IDEA' in revision 1

この例ではもちろん、現在の IDEAファイルは リビジョン 1 では存在しなかったので Subversion はエラーを出します。 上のコマンドはペグ・リビジョンを明示的に指定する、より長い形の形式 の略記法です。長い形式は以下のようになります:

$ svn cat -r 1 concept/IDEA@BASE
svn: Unable to find repository location for 'concept/IDEA' in revision 1

And when executed, it has the expected results.

The perceptive reader is probably wondering at this point if the peg revision syntax causes problems for working copy paths or URLs that actually have at signs in them. After all, how does svn know whether news@11 is the name of a directory in my tree, or just a syntax for 「revision 11 of news」? Thankfully, while svn will always assume the latter, there is a trivial workaround. You need only append an at sign to the end of the path, such as news@11@. svn only cares about the last at sign in the argument, and it is not considered illegal to omit a literal peg revision specifier after that at sign. This workaround even applies to paths that end in an at sign—you would use filename@@ to talk about a file named filename@.

今度はもう一方の質問をしてみましょう。つまり —リビジョン 1 の時点で、とにかく concepts/IDEAという名前で 存在していたファイルの内容はどんなものでしたか? これを指定する ために明示的なペグ・リビジョンを使います。

$ svn cat concept/IDEA@1
The idea behind this project is to come up with a piece of software
that can frab a naggily wort.  Frabbing naggily worts is tricky
business, and doing it incorrectly can have serious ramifications, so
we need to employ over-the-top input validation and data verification
mechanisms.

Notice that we didn't provide an operative revision this time. That's because when no operative revision is specified, Subversion assumes a default operative revision that's the same as the peg revision.

As you can see, the output from our operation appears to be correct. The text even mentions frabbing naggily worts, so this is almost certainly the file which describes the software now called Frabnaggilywort. In fact, we can verify this using the combination of an explicit peg revision and explicit operative revision. We know that in HEAD, the Frabnaggilywort project is located in the frabnaggilywort directory. So we specify that we want to see how the line of history identified in HEAD as the path frabnaggilywort/IDEA looked in revision 1.

$ svn cat -r 1 frabnaggilywort/IDEA@HEAD
The idea behind this project is to come up with a piece of software
that can frab a naggily wort.  Frabbing naggily worts is tricky
business, and doing it incorrectly can have serious ramifications, so
we need to employ over-the-top input validation and data verification
mechanisms.

そして、ペグ・リビジョンも操作対象リビジョンも、時には非常に重要な意味 を持ちます。例えば、 frabnaggilywortがリビジョン 20 で HEAD から削除されているが、リビジョン 20 では 存在していたことを知っていて、その時の IDEA ファイルが、リビジョン 4 と リビジョン 10 の間でどのように変化したか を見たいとします。これには、ペグ・リビジョン 20 を、そのリビジョンで Frabnaggilywort の IDEAファイルを保持していた URL の後につけて指定します。また同時に操作対象リビジョン範囲として 4 と 10 を指定します。

$ svn diff -r 4:10 http://svn.red-bean.com/projects/frabnaggilywort/IDEA@20
Index: frabnaggilywort/IDEA
===================================================================
--- frabnaggilywort/IDEA        (revision 4)
+++ frabnaggilywort/IDEA        (revision 10)
@@ -1,5 +1,5 @@
-The idea behind this project is to come up with a piece of software
-that can frab a naggily wort.  Frabbing naggily worts is tricky
-business, and doing it incorrectly can have serious ramifications, so
-we need to employ over-the-top input validation and data verification
-mechanisms.
+The idea behind this project is to come up with a piece of
+client-server software that can remotely frab a naggily wort.
+Frabbing naggily worts is tricky business, and doing it incorrectly
+can have serious ramifications, so we need to employ over-the-top
+input validation and data verification mechanisms.

ありがたいことにほとんどのユーザはこんな複雑な状況に出会うことはありま せん。しかし万一そんなことになった場合には、Subversion がファイル名の あいまいさを解消するにはペグ・リビジョンを追加で指定してやれば良いこと は覚えておいてください。



[18] You're not supposed to name it. Once you name it, you start getting attached to it.」—Mike Wazowski

[19] 606 N. Main Street, Wheaton, Illinois, は Wheaton 歴史センターのある場所です。 たずねてみてください—「歴史センター」だって? 確かに….