版本控制(译文)-5 (连载)

译:只是路过

Chapter 5: Working Folders

第五章:工作目录

This is part of an online book called Source Control HOWTO, a best practices guide on source control, version control, and configuration management.

这是一篇名为如何做源码控制的在线书籍的一部分,一本关于源码控制、版本控制、配置管理的最佳实践手册。

The joy of indifference

无关紧要的喜悦

CVS calls it a sandbox.  Subversion calls it a working directory.  Vault calls it a working folder.  By any of these names, a working folder is a directory hierarchy on the developer's client machine.  It contains a copy of the contents of a repository folder.  The very basic workflow of using source control involves three steps:

1.      Update the working folder so that it exactly matches the latest contents of the repository.

2.      Make some changes to the working folder.

3.      Checkin (or commit) those changes to the repository.

CVS称之为一个沙箱。Subversion称之为一个工作文件夹。Vault称之为一个工作文件夹。不管什么名字,工作文件夹都是一个层级目录,存放在开发者的客户端机器上。它包含了一个库文件夹的内容的拷贝。使用源码控制工具的最基本的工作流程包括下面三个步骤:

1.        更新工作目录,以保持它刚好同最新的库内容匹配

2.        在工作目录进行一些变更

3.        签入或提交那些变更到库里面

The repository is the official archive of our work.  We treat our repository with great respect.  We are extremely careful about what gets checked in.  We buy backup disks and RAID arrays and air conditioners and whatever it takes to make sure our precious repository is always comfortable and happy.

库是我们的正式的档案。我们对我们的库要非常的尊敬。我们需要相当小心签入什么到里面。我们要买来备份盘或者RAID阵列或者空调或者任何能够使我们之前的库始终舒适和高兴的东西。

Best Practice: Don't let your working folder become too valuable
最佳实践:不要让你的工作目录变得太有价值。
Checkin your work to the repository as often as you can without breaking the build.

当你可以不中断构建的时候就签入你的工作到库里面。

In contrast, we treat our working folder with very little regard.  It exists for the purpose of being abused.  Our working folder starts out worthless, nothing more than a copy of the repository.  If it is destroyed, we have lost nothing, so we run risky experiments which endanger its life.  We attempt code changes which we are not sure will ever work.  Sometimes the contents of our working folder won't even compile, much less pass the test suite.  Sometimes our code changes turn out to be a Really Bad Idea, so we simply discard the entire working folder and get a new one.

相对来说,我们对待我们的工作目录可以不怎么尊重。它存在的目的就是被滥用。我们的工作目录基本没有价值,仅仅是一个库的拷贝而已。如果它被破坏了,我们没有失去任何东西,所以我们可以对其进行危及其生命的任何危险试验。有的时候,我们的工作目录的内容甚至不被编译,或者通过测试集合进行测试,有时我们的代码变更变成一个真正的坏主意,我们可以简单的放弃整个工作目录然后获得一个新的。

But if our code changes turn out to be useful, things change in a very big way.  Our working folder suddenly has value.  In fact, it is quite precious.  The only copy of our most recent efforts is sitting on a crappy, laptop-grade hard disk which gets physically moved four times a day and never gets backed up.  The stress of this situation is almost intolerable.  We want to get those changes checked in to the repository as quickly as possible. 

但是,如果我们的代码变更变得有用,事情就非常彻底的变化了。我们的工作目录突然就变得有价值了。事实上,它相当的珍贵。这个包含了我们最近的努力的唯一的拷贝却被置于没有价值的地位,随移动硬盘物理上一天移动四次,而且从不备份。这种情况的压力简直难以忍受。我们打算尽可能快的取得那些签入到库的变更。

Once we do, we breathe a sigh of relief.  Our working folder has once again become worthless, as it should be.

一旦我们做了,我们就松了一口气。我们工作目录又变得没有价值了,象它本来就该的那样。

Hidden state information

Once again I need to spend some time explaining grungy details of how SCM tools work.  I don't want to repeat the apology I used in the last chapter, so the following line of "code" should suffice:

Response.Write(previousChapter.Section["Cars and Clocks"]);

被隐藏的状态信息

又一次我需要花些时间解释软件配置管理工具如何工作的陈词滥调。我不想重复的为我在上一个章节的描述道歉所以下面这一行代码应该能够满足需求:

Response.Write(previousChapter.Section["Cars and Clocks"]);

Best Practice: Use non-working folders when you are not working
最佳实践:当你没有工作的时候使用不工作的目录
SCM tools need this "hidden state information" so it can efficiently keep track of things as you make changes to your working folder. However, sometimes you want to retrieve files from the repository with no plan of making changes to them. For example, if you are retrieving files to make a source tarball, or for the purpose of doing an automated build, you don't really need the hidden state information at all.
软件配置管理工具需要这个“被隐藏的状态信息”,所以它可以在你在工作目录进行变更的时候,有效的保持对事件的跟踪。然而,有时你在没有计划变更的情况下想从库里重新取得文件。如:如果你想取的文件来生成一个源Tarball,或者基于做一个自动构建的目的,你真的不需要被隐藏的状态信息。
Your SCM tool probably has a way to retrieve things "plain", without writing the hidden state information anywhere. I call this a "non-working folder". In Vault, this is done automatically whenever you retrieve files to a destination which is not configured as the working folder, although I sometimes wish we had made this functionality a completely separate command.

你的配置管理工具可能还有一个方式来取得“普通的”东西,不用写被隐藏的信息,我称这为一个“非工作目录”。在Vault里面,无论何时你取文件到一个没有被配置成为工作目录的地方,这些都被自动完成,当然,我有时希望我们可以把这个功能作为一个完全独立的命令。

Let's suppose I have a brand new working folder.  In other words, I started with nothing at all and I retrieved the latest versions from the repository.  At this moment, my new working folder is completely in sync with the contents of the repository.  But that condition is not likely to last for long.  I will be making changes to some of the files in my working folder, so it will be "newer" than the repository.  Other developers may be checking in their changes to the repository, thus making my working folder "out of date".  My working folder is going to be new and old at the same time.  Things are going to get confusing.  The SCM tool is responsible for keeping track of everything.  In fact, it must keep track of the state of each file individually.

我们假设我有一个全新的工作目录。换句话说,我根本不要任何东西来开始,并且我从库里取得了最近的版本。这个时候,我的新工作目录和库里的内容完全同步。但是那种情况不可能维持太久。我将在我的工作目录里面对一些文件进行变更,那工作目录就会比库“新一点儿”。其他的开发人员可以签入他们的变更到库里面,从而我的工作目录“过期了”。也就是说我的工作目录几乎在同一时间即是新的又过期了。事态变得复杂。源码控制工具有责任追踪任何事情。事实上,它必须保留每个文件单独的状态追踪记录。

For housekeeping purposes, the SCM tool usually keeps a bit of extra information on the client side.  When a file is retrieved, the SCM client stores its contents in the corresponding working file, but it also records certain information for later.  Examples:

为了常规事务管理的目的,配置管理工具通常在客户端保留了一点特殊的信息。当一个文件被取出来,配置管理客户端存储了它在工作文件中相应的内容,但是它同样记录了一定的信息。例如:

  • Your SCM tool may record the timestamp on the working file, so that it can later detect if you have modified it. 
  • It may record the version number of the repository file that was retrieved, so that it may later know the starting point from which you began to make your changes. 
  • It may even tuck away a complete copy of the file that was retrieved, so that it can show you a diff without accessing the server.
  • 你的配置管理工具可以在工作文件上记录时间戳,所以它在你修改的时候可以监测到。
  • 它可以记录你从库里面取得的文件的版本数,它后来知道你开始进行变更的起始点。
  • 它可以从取得的文件的整个拷贝里面大肆翻找,它不连接到服务器就能告诉你差别。

I call this information "hidden state information".  Its exact location depends on which SCM tool you are using.  Subversion hides it in invisible subdirectories in your working directory.  Vault can work similarly, but by default it stores hidden state information in the current user's "Application Data" directory.

我称这个信息为“隐藏的状态信息”。它的确切位置依赖于你正在使用的配置管理工具。Subversion隐藏了它,在你的工作目录的一个不可见的子目录里面。Vault可以非常类似的工作,但是它默认在当前用户的“应用程序数据”目录存储了隐藏状态信息。

Working file states

工作文件状态

Because of the changes happening on both the client and the server, a working file can be in one of several possible states.  SCM tools typically have some way of displaying the state of each file to the user.  Vault shows file states in the main window.  CVS shows them in response to the 'cvs status' command.

因为变更是在服务器和客户端都要发生的,一个工作文件能到达几个可能状态中的一个。配置管理工具有一些有特色的方式显示用户的每个文件的状态。Vault在主窗口显示文件状态。CVS通过使用“cvs status”命令显示文件状态。

The table below shows the possible states for a working file.  The column on the left shows my particular name for each of these states, which through no coincidence is the name that Vault uses.  The column on the far right shows the name shown by the 'cvs status' command.  However, the terminology doesn't really matter.  One way or another, your SCM tool is probably keeping track of all these things and can tell you the state of any file in your working folder hierarchy.

下面的表显示了一个工作文件可能有的状态。左边的栏显示这些状态的名称,他们不一定同Vault中使用的名字一致。右边的远点的栏显示了通过“cvs status”命令查看到的名字。当然,术语不是真的要紧的。无论如何,你的配置管理工具可能保持了所有事件的追踪和能够告诉你在你的工作目录层级中任何文件的状态。

State Name

状态名

Has the working file been modified?

工作文件是否被修改?

Does the repository have a newer version than the last one retrieved?

是否比当前获得的有一个更新的库?

Remarks

标签

'cvs status'

CVS状态’

None

No

No

The working file matches the latest version in the repository.

工作文件同目录中的最新版本相匹配

Up-to-date

最新的

Old

No

Yes

 

Needs Patch

需要打补丁

Edited

Yes

No

 

Locally Modified

本地修改

Needs Merge

Yes

Yes

 

Needs Merge

需要合并

Missing

N/A

N/A

The working file does not exist.

这个工作文件不存在。

Needs Checkout

需要签出

Renegade

Yes

No

You have modified a file without first checking it out.

你修改了一个之前没有签出的文件。

N/A

 

Unknown

No

No

There is a working file, but the SCM tool has no hidden state information about it.

这是一个工作文件,但是配置管理工具没有关于它的隐藏状态信息。

Unknown

不知道

 

Refresh

更新

In order to keep all this file status information current, the SCM client must have ways of staying up to date with everything that is happening.  Whenever something changes in the working folders or in the repository, the SCM client wants to know.

为了保持所有文件的当前状态信息,配置管理工具客户端必须不舍昼夜的关注所有发生的事情。不管是在工作目录发生的还是在库里面发生的,客户端都应该知道。

Changes in the working folders on the client side are relatively easy.  The SCM client can quickly scan files in the working folders to determine what has changed.  On some operating systems, the client can register to be notified of changes to any file.

在客户端,工作目录里面的变更都是很简单的关联的。配置管理工具客户端可以很快的就确定哪个文件发生了变化。在一些操作系统里面,客户机可以通过注册来要求得到任何文件变更的提示。

Notification of changes on the server can be a bit trickier.  The Vault client periodically queries the server to ask for the latest version of the repository tree structure.  Most of the time, the server will simply respond that "nothing has changed".  However, when something has in fact changed, the client receives a list of things which have changed since the last time that client asked for the tree structure.

服务器上的变更通知还是有点小聪明的。Vault客户端周期性的询问服务器最近版本的库的树结构。很多时候,服务器都说“没有变化”。但是,当真正有变化的时候,客户端就会收到一个从上次客户端询问过后有什么发生了变化的列表。

For example, let's assume Laura retrieves the tree structure and is informed that foo.cpp is at version 7.  Later, Wilbur checks in a change to foo.cpp and creates version 8.  The next time Laura's Vault client performs a refresh, it will ask the server if there is anything new.  The server will send down a list, informing her client that foo.cpp is now at version 8.  The actual bits for foo.cpp will not be sent until Laura specifically asks for them.  For now, we just want the client to have enough information so that it can inform Laura that her copy of foo.cpp is now "Old".

例如:Laura获得了树的结构,并且被告知foo.cpp正在版本7中。后来,Wilbur签入了一个foo.cpp的变更,并且创建了版本8。下次LauraVault客户端就会执行一次更新,它会问服务器是否有什么发生了变化。服务器就会发送一个下载列表,告诉客户端foo.cpp现在在版本8foo.cpp的实际的内容将不会发送,直到Laura指出需要他们才发送。现在我们希望客户端有充足的信息来通知Laura,她的foo.cpp已经旧了。

Operations that involve a working folder

工作目录中的操作

OK, let's go back to speaking a bit more about practical matters.  In terms of actually usage, most interaction with your SCM tool happens in and around your working folder.  The following operations are the basic things I can do to a working folder:

好啦,我们回头来谈一点关于实践的问题。在实际的使用中,很多的工作目录同配置工具的交互发生了。这下面的操作就是我能在工作目录中做的事情。

Make changes

进行变更

This is the whole point.

这是整个的点。

Review changes

回顾变更

Show me the changes I have made to my working folder so far.

很快的显示在工作目录中做过的变更。

Undo changes

撤销变更

Some of my changes didn't work out the way I planned. Undo them, restoring my working folder back to the way it was when I started.

有时候有的变更不是期望的,那就撤销他们,使工作目录返回到它开始变更前的状态。

Update

更新

The repository has changes which I want to be included in my working folder.

更新当库变化时在工作目录中包含的部分。

Commit changes

提交变更

I'm ready to send my changes to the repository and make them permanent.

将变更放到库中并持久保存下来。

In the following sections, I will cover each of these operations in a bit more detail.

下面的章节里面,我将对这些操作都有一个全面详细的描述。

Make the changes

进行变更

The primary thing you do to a working folder is make changes to it.

你对工作目录做的最重要的事情就是对其进行变更。

In an idealized world, it would be really nice if the SCM tool didn't have to be involved at all.  The developer would simply work, making all kinds of changes to the working folder while the SCM tool eavesdrops, keeping an accurate list of every change that has been made.

理想化的状态是,配置管理工具不用管那么多就好了。开发人员可以单纯的工作,在配置管理工具监听的状态下在工作目录中进行各种变更,还能够对已经做的变更有一个精确的列表。

Unfortunately, this perfect world isn't quite available.  Most operations on a working folder cannot be automatically detected by the SCM client.  They must be explicitly indicated by the user.  Examples:

不幸的是,这种理想化的完美世界不是真的有用。很多在工作目录的操作不能由配置管理工具客户端自动的探测到。他们必须用户明确的指出。例如:

  • It would be unwise for the SCM client to notice that a file is "Missing" and automatically assume it should be deleted from the repository. 
  • Automatically inferring an "Add" operation is similarly unsafe.  We don't want our SCM tool automatically adding any file which happens to show up in our working folder. 
  • Rename and move operations also cannot be reliably divined by mere observation of the result.  If I rename foo.cpp to bar.cpp, how can my SCM client know what really happened?  As far as it can tell, I might have deleted foo.cpp and added bar.cpp as a new file. 
  • 让配置管理工具客户端对提示一个文件“丢失”了,并且自动的假设这个文件可能被从库里删除了这种情况不是很明智的。
  • 自动推测一个“添加”操作也不安全。我们不打算在工作目录出现了任何文件的时候就自动的添加它们。
  • 重命名和移动操作通过只观察结果也同样不可信。如果我重命名foo.cppbar.cpp,那我的配置管理工具客户端又怎样知道真正发生什么?到它告诉我的时候,我可能都删除了foo.cpp文件,然后把bar.cpp当新文件添加了。

All of these so-called "folder-level" operations require the user to explicitly give a command to the SCM tool.  The resulting operation is added to the pending change set, which is the list of all changes that are waiting to be committed to the repository.

所有这些所谓的“目录级”的操作都需要用户明确的给一个命令给配置管理工具。这个操作的结果被添加到变更等待序列中,所有的变更都在这个序列中,等待着被提交到库里面。

However, it just so happens that in the most common case, our "eavesdropping" ideal is available.  Developers who use the edit-merge-commit model typically do not issue any explicit command telling the SCM tool of their intention to edit a file.  The files in their working folder are left in a writable state, so they simply open their text editor or their IDE and begin making changes.  At the appropriate time, the SCM tool will notice the change and add that file to the pending change set.

但是,在很多普通的情况下就会发生,我们的“偷听”行为(译者注:即不需要通知配置管理工具。)可行。开发人员使用典型的“编辑-合并-提交”模式的时候不需要发送命令告诉配置管理工具他们想编辑文件。在他们的工作目录里的文件被处于一个可写状态,然后他们简单的打开他们的文本编辑器或是集成工作环境进行变更。在适当的时候,配置管理工具将注意到变更并将那个文件加入到等待队列。

Users who prefer "checkout-edit-checkin" actually have a somewhat more consistent rule for their work.  The SCM tool must be explicitly informed of all changes to the working folder.  All files in their working folder are usually marked read-only.  The SCM tool's Checkout command not only informs the server of the checkout request, but it also flips the bit on the working file to make it writable.

实际上喜欢使用“签出-修改-签入”的用户对他们的工作要多点固定的规则。配置管理工具必须明确所有工作目录中发生的变更。在工作目录中的文件通常都是被标示只读的。配置管理工具的签出命令不只是告诉服务器签出的请求,它还请求将工作文件变更为可写。

Review changes

回顾变更

One of the most important features provided by a working folder is the ability to review all of the changes I have made.  For SCM tools that do keep track of a pending change set (Vault, Perforce, Subversion), this is the place to start.  The following screen dump shows the pending change set pane from the Vault client, which is showing me that I have currently made two changes in my working folder:

工作目录最重要的一个特性是能够回顾做过的变更。对变更等待序列保持了追踪的配置管理工具(Vault, Perforce, Subversion)而言,工作目录是开始的地方。下面的截图显示了Vault客户端中的变更等待序列,显示了我当前在我的工作目录做的两个变更。

The pending change set view shows all kinds of changes, including adds, deletes, renames, moves, and modified files.  It is helpful to keep an eye on the pending change set as I work, verifying that I have not forgotten anything.

变更等待序列中显示了所有的类型的变更,包括增加、删除、重命名、移动和修改文件。它有助于密切注视我做的那些变更,确证我没有遗忘做任何事情。

However, for the case of a modified file, this visual display only shows me which files have changed.  To really review my changes, I need to actually look inside the modified files.  For this, I invoke a diff tool.  The following screen dump is from a popular Windows diff tool called Beyond Compare:

然而,对于一个更改了的文件,这个界面只是显示我已经变更了哪个文件。要真正的回顾我的变更,我需要真正的查看修改了的文件里的内容。为了这个目的,我使用了一个比较工具。下面的截图是一个叫Beyond Compare的流行的视窗比较工具。

This picture is fairly typical of the visual diff tool genre, showing both files side-by-side and highlighting the parts that are different.  There are quite a few tools like this.  The following screen dump is from the visual diff tool which is provided with Vault:

这个图是一个相当典型的视窗比较工具风格,并行的显示所有文件,然后高亮不同部分。有很多工具都是这样的。下面的图是从Vault提供的界面比较工具截取出来的。

Best Practice: Run diff just before you checkin, every time
最佳实践:每次签入前运行比较工具。

Never checkin your changes without giving them a quick review in some sort of a diff tool.

一定不要在没有通过任何比较工具进行一个快速回顾前就签入你的变更。

The left panel shows version 21 of sgdmgui_props.cpp, which is the current version in the repository.  The right panel shows my working file.  The colored regions show exactly what has changed:

左边的栏显示了sgdmgui_props.cp是在当前库中是版本21。右边显示了工作文件。彩色区域标示了哪些发生了变更:

  • On line 33 I changed the type of this function from long to short.
  • At line 35 I inserted a one-line comment.
  • 33行将函数类型从long变为了short
  • 35行插入了一行注释。

Note that SourceGear's diff tool shows inserted lines by drawing lines in the center gap to indicate exactly where the insertion occurs.  In contrast, Beyond Compare is showing a dead region on the left side across from the inserted line on the right.  This particular issue is a matter of personal preference.  The latter approach does have the benefit that identical lines are always across from each other.

注意:SourceGear的对比工具显示方式是在行中间插入线来指出插入点发生的变化。相对比的,Beyond Compare对应的在右边插入了行的地方的左边显示了一个固定区域。这种细节的表示方式是一种个人爱好。后面这种呢有一个好处是始终在彼此的同一行处都进行了标示。

Both of these tools do a nice job on the modification to line 33, showing exactly which part of the line was changed.  Most of the recent visual diff tools support this ability to highlight intraline differences. 

这些工具对修改第33行都做了一件好事,他们都显示了这行发生了变化。最近流行的视窗比较工具还支持高亮每行内的差别。

Visual diff tools are indispensable.  They give me a way to quickly review exactly what has changed.  I strongly recommend you make a habit of reviewing all of your changes just before you checkin.  You can catch a lot of silly mistakes by taking the time to be sure that your changes look the way you think they look.

视窗比较工具是不可缺少的工具。他们给了我们一个准确、快速回顾什么被变更了的方式。我强烈推荐大家有一个在签入前对变更回顾的习惯。通过花点时间你可能发现一些愚蠢的错误,一定要确保你的变更可以体现你的真实意图。

Undo changes

撤销变更

Sometimes I make changes which I simply don't intend to keep.  Perhaps I tried to fix a bug and discovered that my fix introduced five new bugs that are worse than the one I started with.  Or perhaps I just changed my mind.  In any case, a very nice feature of a working folder is the ability to undo.

有时候我做了我不想保留的变更。可能我试图修改一个错误,但是发现我的修改引入了5个新的错误,比我改之前还更糟糕了。那我就可能改变主意。无论如何,一个工作目录的好的功能就是可以处理撤销变更。

In the case of a folder-level operation, perhaps the Undo command should actually be called "Nevermind".  After all, the operation is pending.  It hasn't happened yet.  I'm not really saying that I want to Undo something which has already happened.  Rather, I am just saying that I no longer want to do something that I previously said I did.

在处理一个目录级的操作的情况时,可能撤销命令可以刚好被称为“不介意”。毕竟,这个操作是没有执行的。它都还没有发生。我真的不想说我要撤销已经发生的任何事情。甚至,我要说我不再希望做上述我做的任何事情。

For example, if I tell the Vault client to delete a file, the file isn't really deleted until a commit that change to the repository.  In the meantime, it is merely waiting around in my pending change set.  If I then tell the Vault client to Undo this operation, the only thing that actually has to happen is to remove it from my pending change set.

例如:如果我告诉Vault删除一个文件,到我提交这个变更请求到库里,这个文件不会被真正的删除的。其间,它只是在我的变更等待序列中等待着。如果我告诉Vault客户端撤销这个操作,那事实上发生的事情只是它被从我的变更等待序列中移走了。

Best Practice: Be careful with undo
最佳实践:撤销要小心
When you tell your SCM client to undo the changes you have made to a file, those changes will be lost. If your working folder has become valuable, be careful with it.

当你要配置管理工具客户端撤销对一个文件做的变更时,那些变更也就丢失了。你的工作目录变得有价值了,小心爱护它!

In the case of a modified file, the Undo command simply overwrites the working file with the "baseline" version, the one that I last retrieved.  Since Vault has been keeping a copy of this baseline version, it merely needs to copy this baseline file from its place in the hidden state information over the working file.

一个变更了的文件在这种情况下,撤销命令用“基线”版本简单的覆盖了工作文件,基线版本就是我之前取得的那个。自从Vault保持了一个基线版本的拷贝以来,它就只需要从被隐藏了状态信息的工作文件的位置之上拷贝基线文件了。

For users who use the checkout-edit-checkin style of development, closely related here is the need to undo a checkout.  This is essentially similar to undoing the changes in a file, but involves the extra step of informing the server that I no longer want the file to be checked out.

对于使用签出-编辑-签入风格进行开发的用户,类似描述就是需要撤销签出。本质上类似撤销对文件的变更,但是包含了一个特殊的步骤,要告诉服务器我不再想这个文件被处于签出状态。

Digression: Your skillet is not a working folder

闲话一下:你的skillet不是一个工作目录

Source control tools have been a daily part of my life for well over a decade.  I can't imagine doing software development without them.  In fact, I have developed habits that occasionally threaten my mental health.  Things would be so much easier if the concept of a working folder were available in other areas of life:

源码控制工具已经成为我日常生活中的一部分有超过十年了。我难以想像开发的时候没有它们。事实上,我已经泄漏了偶尔威胁我的心理健康的习惯。如果工作目录在生活的其他地方也有效的话事情就会简单很多:

  • "Hmmm.  I can't remember which of these pool chemicals I have already done.  Luckily, I can just diff against the version of the pool water from an hour ago and see exactly what changes I have made."
  • "Boy am I glad I remembered to set the read-only bit on my front lawn to remind me that I'm not supposed to cut the grass until a week after the fertilizer was applied."
  • "No worries -- if I accidentally put too much pepper on this chicken, I can just revert to the latest version in the repository."
  • “嗯。我不确定我放了化学药剂到哪个池子里。幸运的是,我可以从一个小时前去对比池水的版本,然后明确我对这些池水做了些什么变更。”
  • “噢,我很高兴我记住把我前面的草坪设置只读状态了,提醒我在施完肥一周后才可以去剪草。”
  • “不要着急――如果我不小心放了很多胡椒粉到鸡肉上面,我可以回到库中的上一个版本。”

Unfortunately, SCM tools are unique.  When I make a mistake in my woodshop, I can't undo it.  Only in software development do I have the luxury of a working folder.  It's a place where I can work without constantly worrying about making a mistake.  It's a place where I can work without having to be too careful.  It's a place where I can experiment with ideas that may not work out.  I wish I had working folders everywhere.

不幸的是,配置管理工具是唯一的。当我在我自己的森林(译者注:此森林是同配置管理工具中复杂的版本树构成的森林进行的类比)里犯了错误,我不能撤销。我在软件开发中拥有这样一个工作目录已经是一种奢侈。这是个我可以不用担心工作出错的地方。这是个我不用太小心工作的地方。这是个我可以实验我不成形的想法的地方。我希望我能够在任何地方都有这样的工作目录。

Update the working folder

更新工作目录

Ten milliseconds after I retrieve a fresh working folder, it might be out of date.  An SCM repository is a busy hub of activity.  New stuff arrives regularly as team members finish tasks and checkin their work.

我得到一个新的工作目录之后十毫秒,它就可能过时了。一个配置管理库就是一个繁忙的活动枢纽。新人成为团队成员开始按团队规则完成任务并签入他们的工作。

I don't like to let my working folder get too far behind the current state of the repository.  SCM tools typically allow the user to invoke a diff tool to compare two repository versions of a file.  When I am working on a feature, I periodically like to review the recent changes in the repository.  Unless those changes look likely to disrupt my own work, I usually proceed to retrieve the latest versions of things so that my working folder stays up to date.

我不喜欢我的工作目录太落后于当前库的状态。配置管理工具允许用户调用一个比较工具来比较一个文件在库中的两个版本。当我写一个功能的时候,我喜欢不时去看看库中的变化。如果那些变更看来不会使我的工作中断,我通常会取得最新的版本来保持我的工作目录同步。

In CVS, the command to update a working folder is [rather conveniently] called 'update'.  In Vault, this operation is done with the Get Latest Version command.  The screen dump below is the corresponding dialog box:

CVS里,更新工作目录的相当便利的命令叫做“更新”。在Vault里面,这个操作是Get Latest Version(取得最近版本)命令完成的。下面截图就是那个对话框:

Best Practice: Don't get too far behind
最佳实践:不要太落后!
Update your working folder as often as you can.

尽可能多的更新你的工作目录。

I want to update my working folder to contain all of the changes available on the server, so I have invoked the Get Latest Version operation starting at the very top folder of my repository.  The Recursive checkbox in the dialog above indicates that this operation will recursively apply to every subfolder.

我希望能够将所有可用的变更都更新到我的工作目录,我就会使用Get Latest Version(取得最近版本)命令在我的配置库顶层开始取最近版本。对话框中的递归选择框指出了这个操作将会递归到每个子目录。

Note that this dialog box gives me a few choices for how I may want to handle situations where a change has happened on both the client and the server.  Let us suppose for a moment that I am not using exclusive checkouts and that somebody else has also modified sgdmgui_props.cpp.  In this case, I have three choices available when I want to update my working folder:

注意,那个对话框为在客户端和服务器都发生了变更时如何处理的情况提供了几个选择。假设有一段时间我没有使用独立锁来签出并且其他人也修改了sgdmgui_props.cpp。既然这样,我打算更新我的工作目录的时候我就有三种选择:

  • Overwrite my working file.  This effect here is similar to an Undo.  My changes will be lost.  Use with care.
  • Attempt automatic merge.  The Vault client will attempt to construct a file which contains my changes and the changes which were made on the server.  If the automerge succeeds, my working file will end up in the "Edited" status.  If the automerge fails, the status of my working file will be "Needs Merge", and the Vault client will nag and pester me until I resolve the situation.
  • Do not overwrite/Merge later.  This option leaves my working file untouched.  However, the status of the file will change to "Needs Merge".  Vault will not allow me to checkin my changes until I affirm that I have done the right thing and merged in the changes from the repository.
  • 覆盖我的工作文件。这类似一个撤销操作。我的变更将会被丢失掉。小心使用!
  • 尝试自动合并。Vault的客户端将试图创建一个包含了我的变更和服务器上已经有的变更的文件。如果自动合并失败了,我的工作文件就会在“编辑”状态终止,然后Vault客户端就缠着我直到我解决这个问题。
  • 之后不要覆盖/合并。这个选项使我的文件变得没有变化过。然而,这个的文件状态会被为改变“需要合并”。直到我确定我做了正确的事情。并且合并了对库的变更,Vault才会允许签入变更。

Note also that the "Prompt for modified files" checkbox allows me to specify that I want the Vault client to allow me to choose between these options for every file that ends up in this situation.

同样还要注意“对修改的文件进行提示”选择框允许我指出:我希望Vault客户端允许我在每个文件结束这个状态的时候在这些选项中进行选择。

As you can see, the Get Latest Version dialog box includes a few other options which I won't describe in detail here.  Other SCM tools have similar abilities, although the user interface may be very different.  In any case, it's a good idea to update your working folder as often as you can.

像你看到的,取得最近版本对话框包含了一些我没有描述的其他选项。其他配置管理工具也有类似的功能,尽管用户界面会有差别。无论如何,这是你能够及时更新你的工作目录的好方法。

Commit changes

提交变更

In most situations, I eventually decide that my changes are Good and should be sent back to the repository so they can become a permanent part of the history of my project.  In Vault, Subversion and CVS, the command is called Commit.  The following screen dump shows the Commit dialog box from Vault:

很多情况下,我都确信我的变更是好的而且应该送回到库里面,那样他们就变成我的项目历史中永久的部分了。在VaultSubversion CVS里面,这个命令称为提交。下面截图显示了Vault的截图:

Note that the listbox at the top contains all of the items in my pending change set.  In this particular example, I only have two changes, but this listbox typically has a scrollbar and contains lots of items.  I can review all of the operations and choose exactly which ones I want to commit to the repository.  It is possible that I may want to checkin only some of my currently pending changes.  (Perforce has a nifty solution to this problem.  The user can have multiple pending change sets, so that changes can be logically grouped together even as they are waiting to be checked in.)

注意,上部的列表框包含了在我的变更等待序列中的项。在这个特殊例子中,我只有两个变更,但是这个列表框在有很多项的时候是有滚动条的。我可以回顾所有做的操作并且准确选择我打算提交到库里面的操作。那就有可能我只想签入我当前变更等待序列中的部分变更。(Perforce对这个问题有一个极好的解决方案。用户可以有多个变更等待序列,变更可以在等待被签入时被逻辑化的分组。)

The "Change Set Comment" textbox offers a place for me to type an explanation of what I changed and why I did it.  Please note that this textbox has a scrollbar, encouraging you to type as much text as necessary to give a full explanation of the problem.  In my opinion, checkin comments are more important than the comments in the actual code.

“变更集合注释”提供了一个地方来解释我变更过什么,为什么变更。请注意这个文本框有一个滚动条,鼓励你录入必要的、对问题足够丰富的解释。我的观点是,签入注释比实际代码中的注释还重要。

When I click OK, all of the selected items will be sent to the server to be committed to the repository.  Since Vault supports atomic checkin transactions, I know that my changes will succeed or fail as a united group.  It is not possible for the repository to end up in a state where only some of these changes made it.

但我点击OK。所有被选中的项就会被送到服务器端,提交到库里面。因为Vault支持签入原子事物,我就会知道我的变更作为一个群组提交是是失败还是成功的。库不可能在只做了其中的一些变更的状态就结束操作。

Remember the discussion in chapter 4 about binary file deltas?  This same technology is also used for checkin operations.  When Vault sends a modified version of a file up to the server, it actually sends only the bytes which have changed, using the same VCDiff format which is used to make repository storage more efficient. 

还记得我们在第四章讨论过的二进制文件增量吗?这是同样的用于签入操作的技术。当Vault客户端发送一个文件的修改版本到服务器上,它实际上只是发送了变更的字节,使用同样的被用于使库存储更有效的VCDiff格式。

The reason this is possible is because it has kept a copy of the baseline file in the hidden state information.  The Vault client simply runs the VCDiff algorithm to construct the difference between this baseline file and the current working file.  So in the case of my running example, the Vault client will send three pieces of information:

这是因为可能在隐藏状态信息中已经保留有一个基线版本了。Vault客户端在基线文件和当前工作文件中简单的运用VCDiff运算法则创建差别。那在我运行示例的情况下,Vault客户端会发送3块信息:

  • The binary delta.  Since the pending change set pane shows that my working file is 40 bytes larger than the baseline where I started, the binary delta is going to be somewhere in the vicinity of 40 bytes long, perhaps with a few extra bytes for overhead.
  • The fact that this binary delta was computed against version 21 of the file.  Since version 21 is known and exists on both the client and the server, the SCM server can simply apply the binary delta to its own copy of version 21 to reconstruct an exact copy of the contents of my working file.
  • The CRC checksum of the original working file.  When the server reconstructs its copy of the working file, the CRC will be compared to ensure that nothing was corrupted during transit.  The file that is stored in the repository will be exactly the same as the working file.  No corruption, no surprises.
  • 二进制增量。自从变更等待序列显示了我的工作文件比我开始变更的时候的基线文件大40字节后,二进制增量也就在40字节左右延伸,可能还有点特殊的字节。
  • 事实是这个文件的二进制增量被在版本21的时候又计算过了。自从版本21被客户端和服务器知道存在开始,配置管理服务器可以简单的应用二进制增量到版本21的拷贝中,并且构建一个关于我的工作文件的精确拷贝。
  • 对原始工作文件的循环冗余检查。当服务器重建工作文件的拷贝的时候,循环冗余检验将对比确认没有任何事情破坏传输。在库中存储的文件将被明确是同工作文件中相同的。没有破坏,就没有惊讶。

Whenever possible, Vault uses binary file deltas "over the wire" in both directions, from client to server as well as from server to client.  In this example, the entire file is only 3,762 bytes, so the savings in network bandwidth isn't all that significant.  However, for larger files, the increase in network performance for offsite users can be quite dramatic.

只要可能,Vault使用二进制增量在任何方向“透过金属丝”从客户端到达服务器也从服务器到达客户端。在这个例子里,整个文件只有3726字节,在宽带网保存不是很大的意义。但是,对于大文件,网络执行效率对离线的用户可以说是相当显著。

This capability of using binary file deltas between client and server is supported by some other SCM tools as well, including (I believe) Subversion and Perforce.

在客户端和服务器间使用二进制增量技术被其他的配置管理工具很好的支持,(我相信)包括SubversionPerforce

When the checkin has completed successfully, if I am working in "checkout-edit-checkin" mode, the SCM tool will flip the read-only bit on my working files to prevent me from accidentally making changes without informing the server of my intentions.

当签入成功完成的时候,如果我是用的“签出-编辑-签入”模式,配置管理工具将在我的工作文件处打上只读标记阻止我意外的、在没有通知服务器的情况下进行变更。

Having completed my checkin, the cycle is completed.  My working folder is once again worthless, since my changes are a permanent part of the repository.  I am ready to start again on my next development task.

在完成签入后,这个周期也就完成了。我的工作目录再次没有价值,因为我的变更已经成为库中永久的部分了。我将开始我的下一个开发任务。

Looking ahead

前瞻

In the next chapter, it's time to start talking about some of the more advanced stuff.  I'll start with an overview of labels and history.

在下一章,是开始讨论一些更深入的问题的时候了。我将开始关于标签和历史的论述。

posted @ 2006-01-09 21:24  margiex  阅读(1131)  评论(0编辑  收藏  举报