Peg和实施修订版本

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. 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. 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? 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. [17] 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 20 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 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.

But what of the --revision (-r) of which we've spoken so much in this book? That revision (or set of revisions) is called the operative revision (or operative revision range). Once a particular line of history has been identified using a path and peg revision, Subversion performs the requested operation using the operative revision(s). To map this to our Chicagoland streets analogy, if we are told to go to 606 N. Main Street in Wheaton, [18] we can think of “Main Street” as our path and “Wheaton” as our peg revision. These two pieces of information identify a unique path that can be travelled (north or south on Main Street), and they keep us from travelling up and down the wrong Main Street in search of our destination. Now we throw in “606 N.” as our operative revision of sorts, and we know exactly where to go.

Say that long ago we created our repository, and in revision 1 added our first concept directory, plus an IDEA file in that directory talking about the concept. After several revisions in which real code was added and tweaked, we, in revision 20, renamed this directory to frabnaggilywort. By revision 27, we had a new concept, a new concept directory to hold it, and a new IDEA file to describe it. And then 5 years and 20 thousand revisions flew by, just like they would in any good romance story.

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 question. 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

Of course, in this example, the current IDEA file didn't exist yet in revision 1, so Subversion gives an error. The previous command is shorthand for a longer notation which explicitly lists a peg revision. The expanded notation is:

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

当执行时,它包含期望的结果。

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 cares only 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路径的文件的内容到底是什么?我们会使用一个明确的peg修订版本来帮助我们完成。

$ 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.

注意我们这一次没有提供操作修订版本,那是因为如果没有指定操作修订版本,Subversion假定缺省的操作修订版本是peg修订版本。

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 that 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.

而且peg修订版本和实施修订版本也不需要这样琐碎,举个例子,我们的frabnaggilywort已经在HEAD删除,但我们知道在修订版本20它是存在的,我们希望知道IDEA从修订版本4到10的区别,我们可以使用peg修订版本20和IDEA文件的修订版本20的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.

幸运的是,几乎所有的人不会面临如此复杂的情形,但是如果是,记住peg修订版本是帮助Subversion清除混淆的额外提示。



[17] 你不是被期望去命名它,一旦你取了名字,你开始与之联系在一起。” — Mike Wazowski

[18] 606 N. Main Street, Wheaton, Illinois, is the home of the Wheaton History Center. It seemed appropriate….