版本控制系统(译文)4 - 文件合并

                          译:只是路过

Chapter 3: File Merge

第三章:文件合并

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

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

How did we get ourselves into this mess?

There are several reasons why we may need to merge two modified versions of a file:

  • When using "edit-merge-commit" (sometimes called "optimistic locking"), it is possible for two developers to edit the same file at the same time.
  • Even if we use "checkout-edit-checkin", we may allow multiple checkouts, resulting once again in the possibility of two developers editing the same file.
  • When merging between branches, we may have a situation where the file has been modified in both branches.

我们是如何让自己陷入胡乱的?

我们为什么需要将两个版本合并到一个文件,有几个原因:

l          在使用“编辑-合并-提交”(有时被称为“开放锁“)的时候,可能两个开发人员在同一时间修改同一个文件。

l          即使使用“签出-修改-签入“也可以允许多重签出,结果可能又是两个开发人员在同一时间修改同一个文件。

l          在两个分支之间合并的时候,需要有个地方来存放这个在两个分支中都被修改了的文件。

In other words, this mess only happens when people are working in parallel.  If we serialize the efforts of our team by never branching and never allowing two people to work on a module at the same time, we can avoid ever facing the need to merge two versions of a file.

换句话说,混乱只在开发人员并行开发的时候发生。如果我们的团队能够有保证从不分支、从不允许开发人员在同一时间修改同一模块的优良传统,我们就能够避免面对合并一个文件的两个版本的情况。

However, we want our developers to work concurrently.  Think of your team as a multithreaded piece of software, each developer running in its own thread.  The key to high performance in a multithreaded system is to maximize concurrency.  Our goal is to never have a thread which is blocked on some other thread.

然而,我们却希望开发人员并发工作。将团队假设为一个软件的一个线程,每个开发人员都在他们自己的线程上运行。高效运行的关键是如何最好的优化并发。我们的目的是永远都不要一个线程堵塞了其他的线程。

So we embrace concurrent development, but the threading metaphor continues to apply.  Multithreaded programming can sometimes be a little bit messy, and the same can be said of a multithreaded software team.  There is a certain amount of overhead involved in things like synchronization and context switching.  This overhead is inevitable.  If your team is allowing concurrent development to happen, it will periodically face a situation where two versions of a file need to be merged into one.

因此我们拥抱并发开发(译者:此处直译拥抱是模仿XP),但是思路隐喻陆续应用。多线程编程有的时候有点混乱,这也可以用来形容一个多线程的软件团队。在类似同步和上下文相关这类事情上,可以确信费用是很棘手的问题。但是这个费用是不可避免的。如果你的团队允许并发开发,它就得周期性的面对一个文件的两个版本需要合并成一个的情况。

In rare cases, the situation can be properly resolved by simply choosing one version of the file over the other.  However, most of the time, we actually need to merge the two versions to create a new version. 

罕见的例子是这种情况下能够简单的选择文件的一个版本覆盖另一个。然而,大多数的时候,我们实际上需要合并两个版本来创建一个新版本。

What do we do about it?

我们能做点什么?

Let's carefully state the problem as follows:  We have two versions of a file, each of which was derived from the same common ancestor.  We sometimes call this common ancestor the "original" file.  Each of the other versions is merely the result of someone applying a set of changes to the original.  What we want to create is a new version of the file which is conceptually equivalent to starting with the original and applying both sets of changes.  We call this process "merging".

下面非常小心谨慎的来描述这个问题:我们有一个文件的两个版本,他们都是来自同一个祖先。我们有的时候称这种祖先为“源”文件。任何一个其它的版本都仅仅是某人对源文件执行的变更。我们打算创建的是一个文件的新版本,从概念上讲这个文件始于源文件并接受了所有的变更。我们称这样的过程为“合并”。

The difficulty of doing this merge varies greatly for different types of files.  How would we perform a merge of two Excel spreadsheets?  Two PNG images?  Two files which have digital signatures?  In the general case, the only way to merge two modified versions of a file is to have a very smart person carefully construct a new copy of the file which properly incorporates the correct elements from each of the other two.

困难的是合并因不同类型的文件而非常多样化。我们怎样合并两个Excel表?两个PNG格式的图片?两个带数字签名的文件?通常,唯一的办法就是合并一个文件的两个被修改了的版本,让一个非常聪明的人小心的创建这个文件的新的副本,这个副本刚好合并了两个版本当中正确的元素。

However, in software and web development there is a special case which is very common.  As luck would have it, most source code files are plain text files with an average of less than 80 characters per line.  Merging files of this kind is vastly simpler than the general case.  Many SCM tools contain special features to assist with this sort of a merge.  In fact, in a majority of these cases, the two files can be automatically merged without requiring the manual effort of a developer.

但是,软件开发或是网站开发都有一个非常普遍的特殊情况。非常幸运的是,大多数的源代码文件,差不多80%的情况都是纯文本文件。合并这种类型的文件比合并普通的简单得多。一些配置管理工具包含支持这种合并的特殊功能。事实上,大多数情况下,两个文件可以不需要开发人员手工操作而自动合并。

An example

一个示例

Let's call our two developers Jane and Joe.  Both of them have retrieved version 4 of the same file and both of them are working on making changes to it.

我们有两个开发人员JaneJoe。他们都从一个文件的4版本的时候取得该文件,然后各自都在更改该文件。

One of these developers will checkin before the other one.  Let's assume it is Jane who gets there first.  When Jane tries to checkin her changes, nothing unusual will happen.  The current version of the file is 4, and that was the version she had when she started making her changes.  In other words, version 4 was her baseline for these changes.  Since her baseline matches the current version, there is no merge necessary.  Her changes are checked in, and a version of the file is created in the repository.  After her checkin, the current version of the file is now 5.

他俩中的一个开发人员会先签入文件。假设是Jane先完成。当Jane打算签入她修改好的东西的时候,通常什么都不会发生。当前版本是4,这是Jane开始变更的时候她拥有的那个版本。换言之,版本4是这些变更的基线。自从她的当前版本同基线匹配以来,都没有重要的合并。她的变更被签时,在配置库中,文件的一个新版本被创建。到她签入完成之后,文件的当前版本就变为5了。

The responsibility for merging is going to fall upon Joe.  When he tries to checkin his changes, the SCM tool will protest.  His baseline version is 4, but the current version in the repository is now 5.  If Joe is allowed to checkin his version of the file, the changes made by Jane in version 5 will be lost.  Therefore, Joe will not be allowed to checkin this file until he convinces the SCM tool that he has merged Jane's version 5 changes into his working copy of the file.

合并的责任就落到了Joe身上了。当他签入他的变更的时候,配置管理工具开始拒绝。他的基线版本是4,但是在配置库中的当前版本是5。如果Joe被允许签入他的文件,那Jane做的在版本5中的变更就会被丢失掉。然而,直到JOE使配置管理工具确信他已经合并了Jane的版本5的变更到他更改的那个文件的副本中,他才会被允许签入这个文件。

Vault reports this situation by setting the status on this file to be "Needs Merge", as shown in the screen dump below:

Vault 通过在文件上设置“需要合并”的状态来报告这种情况,如下图所示:

Best Practice: Keep the repository in sight

最佳实践:保持配置库被看到

This example happens to involve the need to merge only a single checkin.  Since Joe's baseline is 4 and the current repository version  is 5, Joe is only 1 version out of date.  If the repository version were 25 instead of 5, then Joe would be 21 versions out of date instead of just 1, but the technique is the same.  No matter how old his baseline is, Joe still needs to retrieve the latest version and do a three-way merge.  However, the older his baseline, the more likely he is to encounter conflicts in the merge.

这个例子仅仅是在一个单独的签入需要合并的时候发生。从Joe的基线是4而当前配置库版本是5开始,Joe只有一个版本过期。如果这个配置库的版本是25而不是5,那Joe就有21个版本而不是1个版本过期,因为技术是一样的。不管他的基线有多旧,Joe仍然需要取得最近的一个版本并且作一个三向的合并。然而,他的基线越旧他就越可能遇上合并的冲突。

Keep in touch with the repository.  Update your working folder as often as you can without interrupting your own work. Commit your work to the repository as often as you can without breaking the build. It isn't wise to let the distance between your working folder and the repository grow too large.

同配置库保持联系。 每当你不会打断你的工作的情况下,更新工作目录。每当你可以不中断构建的时候提交你的工作到配置库中。随着库的不断增大,增加你的工作目录同库之间的间隔(译者注:时间上的间隔)是不明智的。

In order to resolve this situation, Joe effectively needs to do a three-way comparison between the following three versions of the file:

  • Version 4 (the baseline from which he and Jane both started)
  • Version 5 (Jane's version)
  • Joe's working file (containing his own changes)

为了解决这个问题,Joe 事实上需要做一个在以下三个版本间的三向比较:

l          版本4JoeJane共同开始的基线)

l          版本5Jane的版本)

l          Joe的工作文件(包含了他自己的变更)

Version 4 is the common ancestor for both Joe's version and Jane's version of the file.  By running a diff between version 4 and version 5, Joe can see exactly what changes Jane made.  He can use this information to apply those changes to his own version of the file.  Once he has done so, he can credibly claim that his version is a merge of his changes and Jane's.

版本4JoeJane的文件来讲都是一个普通的祖先。在45版本间查看区别,Joe能准确的看到Jane做的变更。他可以利用这些信息来把那些变更应用到他自己的那个版本的文件里面。一旦他这样做了,他就可以确切的声称他的文件版本是合并了他自己和Jane的变更。

Strictly speaking, Joe is responsible for whatever changes Jane made, regardless of how difficult the merge may be.  He must perform the changes to his file that Jane would have made if she has started with his file instead of with version 4.  In theory, this could be very difficult:

  • What happens if Jane changed some of the same lines that Joe changed, but in different ways?
  • What happens if Jane's changes are functionally incompatible with Joe's?
  • What happens if Jane made a change to a C# function which Joe has deleted?
  • What happens if Jane changed 80 percent of the lines in the file?
  • What happens if Jane and Joe each changed 80 percent of the lines in the file, but each did so for entirely different reasons?
  • What happens if Jane's intent was not clear and she cannot be reached to ask questions?

严格的来说,不管这个合并有多么的困难,JoeJane的任何变更都要负责。如果Jane是从他的文件开始而不是从版本4开始变更文件,他必须完成他的那个文件。理论上,这可能非常困难:

l          如果Jane用同Joe不同的方式在Joe变更的一些行做了变更,将发生什么?

l          如果Jane的变更刚好从功能上和Joe的相反,将发生什么?

l          如果Jane是对一个Joe删除了的C#的功能进行修改,将发生什么?

l          如果Jane更改了这些行的80%,将发生什么?

l          如果JaneJoe每个人都更改了这些行的80%,只是彼此修改是为了完全不同的原因,将发生什么?

l          如果Jane意图不明且不能引申的问任何更深入的问题,将发生什么?

 

All of these situations are possible, and all of them are Joe's responsibility.  He must incorporate Jane's changes into his file before he can checkin a version 6.

所有这些情况都是可能的,并且他们都是Joe的职责。在他签入版本6之前他必须合并Jane的变更到他的文件里面。

In certain rare situations, Joe may examine Jane's changes and realize that his version needs nothing from Jane's version 5.  Maybe Jane's change simply isn't relevant anymore.  In these cases, the merge isn't needed, and Joe can simply declare the merge to be resolved without actually doing anything.  This decision remains subject to Joe's judgment.

在某些很罕见的情况下,Joe可能会测试Jane做的变更并确定他的版本不需要来自Jane的版本5的任何东西。可能Jane的变更很简单,没有什么关联的。在这些情况下,合并不是必须的,Joe可以简单的声明这个合并实际上没有做什么事情。这个结论取决于Joe的判断。

 

However, most of the time it will be necessary for the merge to actually happen.  In these cases, Joe has the following options:

  • Attempt to automerge
  • Use a visual merge tool
  • Redo one set of changes by hand

Each of these will be explained further in the sections below.

当然,多数时间合并的发生是真正有必要的。这些情况下,Joe有如下选项:

l          尝试自动合并

l          用一个视窗工具

l          手工重做变更

每个选项都会在下面部分深入解释。

Attempt to automerge

试图自动合并

As I mentioned above, a surprising number of cases can be easily handled automatically.  Most source control tools include the ability to attempt an automatic merge.  The algorithm uses all three of the involved versions of the file and attempts to safely produce a merged version.

像我前面提及的那样,数量惊人的合并可以被简单的自动提交。很多的配置控制工具都包含了自动合并的能力。运算法则使用到了所有这个文件的三个版本,并且试图安全的生成一个合并版本。

Best Practice: Only use "automerge on get"

最佳实践:只使用“获取的时候自动合并”

It is widely accepted that SCM tools should only attempt automerge on the "get" of a file. In other words, when Joe realizes that he must merge in the changes Jane made between version 4 and version 5, he will tell his SCM client application to "get" version 5 and attempt to automatically merge it into his working file.  CVS, Subversion and Vault all function in this manner.

普遍承认:配置管理工具应该只是在“获取”一个文件的时候提供自动合并。换句话说,当Joe意识到他必须合并Jane在版本4和版本5中制造的变更,他将告诉他的配置管理客户端应用“获取“版本5和试图自动化合并版本5到他的工作文件中。CVSSubversionVault的所有功能都是这种方式。

Unfortunately, SourceSafe attempts to "automerge on checkin". This is just a really bad idea. When Joe tries to checkin his changes, SourceSafe attempts the automerge.  If it believes that it has succeeded, then his changes are checked in and version 6 was created.  However, it is possible that Joe never examined version 6, or even compiled it.  The repository now contains a file which has never existed in the working folder of any developer on earth.  Its contents have never been seen by human eyes, and it has never been run through a compiler.  Automerge is safe, but it's not  that safe.

不幸的是,SourceSafe 试图在“签入时自动合并。这真的是一个坏主意。当Joe试图签入他的变更的时候,SourceSafe准备自动合并。如果SourceSafe相信它已经成功了,那么他的变更就被签入并且版本6被创建。然而,可能的是Joe从来没有检查过版本6,或者编译过它。配置库中这时就包含了一个事实上从来不存在任何开发人员工作目录中的文件。那些内容也从来没有被人们的肉眼看到,它也从来没有被编译器运行过。自动合并是安全的,但是它又不是那么安全。

It is much better to "automerge on get". This way, the developer can (and should) examine the file after the automerge has happened. This simple change makes it easier to trust automerge.  Instead of trying to do the developer's job, automerge simply becomes a tool which the developer can use to get his job done faster.

最好是“获取的时候自动合并“。这个方式下,开发人员能够(并且应该)在自动合并发生后测试文件。这个简单的变更使得自动合并变得简单可信些了。试图替代开发人员工作,自动合并简单的变成了一个工具,开发人员可以用来更快的将他们的工作取下来。

 

The reason that automerge is so safe in practice is that the algorithm is extremely conservative.  Automerge will refuse to produce a merged version if Joe's changes and Jane's changes appear to be in conflict.  In the most obvious case, if Joe and Jane both modified the same line, automerge will detect this "conflict" and refuse to proceed.  In other cases, automerge may fail with conflicts if two changes are too close to each other.

在实际中自动合并都很安全是因为这个运算规则相当的传统。如果Joe的变更和Jane的变更看上去冲突的话,自动合并就拒绝生成一个合并的版本。很多显而易见的情况下,如果JoeJane都更改了同一行,自动合并会保护这个冲突并且决绝再进行下去。在其他情况下,如果两个变更互相之间太靠近,自动合并会对这种冲突处理失败。

Use a visual merge tool

使用视窗化合并工具

In cases where automerge cannot automatically resolve conflicts, we can use a visual merge tool to make the job easier.  These tools provide a visual display which shows all three files and highlights exactly what has changed.  This makes it much easier for the developer to perform the merge, since she can zero in on the conflicts very quickly.

万一自动合并不能自动合并解决冲突,我们可以用一个视窗合并工具来使这个工作简单些。这些工具提供了视窗显示,显示了所有三个文件和准确的高亮那些变更、这使得它能够在开发人员执行变更更简单,因为它可以非常迅速的集中注意力在冲突上。

There are several excellent visual merge tools available, including Guiffy and  Araxis Merge.  The following screen dump is from "SourceGear DiffMerge", the visual merge tool which is included with Vault.  (Please note sometimes I have to reduce the size of screen dumps to make them fit.  In those cases, you can click on the image to see it at full resolution).

有几个非常优秀的视窗合并工具可用,包括Guiffy  Araxis Merge。下面的图就是从"SourceGear DiffMerge"截取的,这个是Vault中包含的视窗合并工具。(请注意,有的时候我缩小了截图尺寸来适应屏幕,这个时候你可以点击这个图片看全图)

This picture is typical of other three-way visual merge applications.  The left pane shows Jane's version of the file.  The right pane shows Joe's version.  The center pane shows the original file, the common ancestor from which they both started to make changes.  As you can see, Jane and Joe have each inserted a one-line comment.  By right-clicking on each change, the developer can choose whether to apply that change to the middle pane.  In this example, the two changes don't conflict.  There is no reason that the resulting file cannot incorporate both changes.

这个图是一个典型的三向视窗合并应用。左边的窗格显示了Jane的文件的版本。右边窗格显示了Joe的版本。中间的窗格显示了原始文件,这是他们共同开始变更的共同的祖先。如你所见,JaneJoe都有嵌入一个一条线的注释。在每个变更处右击,开发人员可以选择是否应用这个变更到中间窗格。在这个例子中,两个变更没有冲突,就没有道理结果文件不能合并所有的变化。

The following picture shows an example of changes which are conflicting.

下面一个图片显示了一个起了冲突的变更的例子。

Both Jane and Joe have tried to change the wording of this comment.  In the original file, the word used in the comment was "Global".  Jane decided to change this word to "Worldwide", but Joe has changed it to the word "Rampant".  These two changes are conflicting, as indicated by the yellow background color being used to display them.  Automerge cannot automatically handle cases like these.  Only a human being can decide which change to keep.

JaneJoe试图变更注释中的文字。在原始文件中,注释使用到的词是“Global“。Jane决定变更这个单词为”“Worldwide,但是Joe有把这个词改为了“Rampant”。这两个变更就正好冲突,他们被黄色背景色标识。自动合并不能够自动处理这种情况。只有人工可以决定那些变更要保留。

The visual merge tool makes it easy to handle this situation.  I can decide which change I want to keep and apply it to the center pane.

视窗合并工具使得这种情况的处理简单了。我能够决定哪个变化我想保留并应用到中间视窗。

A visual merge tool can make file merging a lot easier by quickly showing the developer exactly what has changed and allowing him to specify which changes should be applied to get the final merged result.

视窗合并工具通过准确显示开发人员做的变更和允许他指定什么变更可以应用到最后的合并结果,使文件合并更简单快捷了。

However, as useful as these kinds of tools can be, they're not magic.

无论如何,像这些类型的工具可以有益一样,他们不是魔术。

 

Redo one set of changes by hand

手工重做一系列变更

Some situations are so complicated that a visual merge tool just isn't very helpful.  In the worst case scenario, Joe might have to manually redo one set of  changes.

有的情况是相当复杂,以至于视窗工具都变得不那么有用了。最坏的场景就是,Joe可能要不得不用手重做一系列的变更。

This situation recently happened here at SourceGear.  We currently have Vault development happening in two separate branches:

  • When we shipped version 2.0, we created a branch for maintenance of the 2.0 release.  This is the tree where we develop minor bug fix releases like 2.0.1.
  • Our "trunk" is the place where active development of the next major release is taking place.

这个情况最近在“SourceGear”工具中出现。我们通常让Vault的发展从两个独立的分支开始:

l          当我们发行版本2.0时,我们就创建一个2.0版本的维护分支。这是我们进行小的缺陷修复的版本树,例如2.0.1

l          我们的“主干“是下一个主发布版本发生主要活动的地方。

Obviously we want any bug fixes that happen in the 2.0 branch to also happen in the trunk so that they can be included in our upcoming 2.1 release.  We use Vault's "Merge Branches" command to migrate changes from one place to the other.

显然我们希望一些缺陷的修复是发生在2.0分支上,也就是主干上,那样他们就可以被包含到新的2.1发布版本中。我们用Vault的“合并分支”命令来使变更从一个地方迁移到另一个地方。

I will talk more about branching and merging in a later chapter.  For now, suffice it to say that the merging of branches can create exactly the same kind of three-way merge situation that we've been discussing in this chapter.

我将在后面的章节更多的描述分支和合并。现在呢,足以说明分支的合并能够准确的创建同样的类型的三向合并,这个情况正是我们在这个章节讨论的。

In this case, we ended up with a very difficult merge in the sections of code that deal with logins. 

  • In the 2.0 branch, we implemented a fix to prevent dictionary attacks on passwords.  We considered this a bug fix, since it is related to the security of our product.  In concept this change was simple.  We simply block login for any account which is seeing too many failed login attempts.  However, implementing this mini-feature required a surprising number of lines to be changed.
  • In the trunk, we added the ability for Vault to authenticate logins against Active Directory.

在这种情况下,我们以一个非常复杂的合并作为结束:在代码段中处理登陆。

l          2.0分支,我们执行一个修复来阻止通过口令的目录攻击。自从它被关联到我们的产品安全,我们考虑这是一个缺陷修复。从概念上来讲这个变更是简单的。我们简单的阻止看上去多次登录失败的任何登录用户。然而,执行这个小的功能需要一个数量惊人的代码行变更

l          在主干上,我们为Vault添加鉴别通过活动目录的登录的能力。

In other words, we made substantial changes to the login code in both these branches.  When it came time to merge, the DiffMerge was extremely colorful.

换句话说,我们在所有的分支的登录代码中制定了一个实质性的变化。当它到了合并的时候,不同合并变得非常有趣。

In this case, it was actually simpler to just start with the trunk version and reimplement the dictionary attack code.  This may seem crazy, but it's actually not that bad.  Redoing the changes takes a lot less time than coding the feature the first time.  We could still copy and paste code from the 2.0 version. 

在这个情况下,事实上恰好从主干版本开始并且再执行一下目录攻击的代码变得简单些了。这看上去比较疯狂,但是实际上并不坏。重新进行变更带来一点时间减少比第一次编写这个功能。我们仍然可以从版本2.0拷贝和复制代码。

Getting back to the primary example, Joe has a choice to make.  His current working file already contains his own set of changes.  He could therefore choose to redo Jane's change starting with his current working file.  The problem here is that he might not really know how.  He might have no idea what Jane's approach was.  Jane's office might be 10,000 miles away.  Jane might have written a lousy comment explaining her checkin.

回到最主要的例子上来,Joe可以有一个选择。他的当前工作文件已经包含了他自己的那些变更。他应该因此选择重新在他当前工作文件的基础上重做Jane的变更。这里的问题是他可能并不真正了解该如何做。他可能没有办法理解Jane的意图。Jane的办公室可能在10公里外。Jane可能只写了一个恶心的注释来解释她的签入。

As an alternative, Joe could set aside his working file, start with the latest repository version and redo his own changes.

作为一个选择,Joe可以把他的工作文件放到一边,从配置库的最后一个版本开始重做他自己的变更。

Bottom line:  If a merge gets this bad, it takes some time and care to resolve it properly.  Luckily, this situation doesn't happen very often.

底线:如果合并使得这糟糕了,就要花时间和更多的细心去正确的解决。很幸运的是,这种情况不经常发生。

Verifying the merge

验证合并

Regardless of which of the above methods is used to complete the merge, it is highly recommended for Joe to verify the correctness of his work.  Obviously he should check that the entire source tree still compiles.  If a test suite is available, he should build and verify that the tests still pass.

无论上面的方法是经常用于解决合并,还是非常推荐Joe验证他的当前工作。显然,他应该检查整个的版本树并编译。如果一个测试集合是必须的,他应该构建并且检查测试直到全部通过。

After Joe has completed the merge and verified it, he can declare the merge to be "resolved", after which the SCM tool will allow him to checkin the file.  In the case of Vault, this is done by using the Resolve Merge Status command, which explicitly tells the Vault client application that the merge is completed.  At this time, Vault would change the baseline version number from 4 to 5, indicating that as far as anyone knows, Joe made his changes by starting with version 5 of the file, not with version 4.

Joe完成了合并和验证之后,在配置管理工具允许他签入之后,他能够声明合并为“已解决”。Vault中,这种情况是通过使用解决合并状态命令来做,那刚好告诉Vault客户端应用合并已经完成。这个时候,Vault可能从45变更基线版本数,以任何人都知道的那样迅速的指出:Joe做他的变更是开始于版本5而不是版本4的。

Since his baseline version now matches the current version of the file, the Vault server will now allow Joe to do his checkin.

因为他的基线版本现在匹配了当前的文件版本,Vault服务器将从现在开始允许Joe签入。

Worth the trouble

麻烦的价值

Best Practice: Give concurrent development a try
最佳实践:对当前开发进行一个尝试
Many teams avoid all forms of concurrent development. Their entire team uses "checkout-edit-checkin" with exclusive locks, and they never branch.
很多团队都避免任何形式的并发开发。他们整个团队都是使用“签出-编辑-签入”以及独立锁,并且从不分支。
For some small teams, this approach works just fine. However, the larger your team, the more frequently a developer becomes "blocked" by having to wait for someone else.
对一些小的团队,这种方式还不错。然而,大一点的团队,很常见的是一个开发人员因为要等待别人而被“封锁”。
Modern source control systems are designed to make concurrent development easy. Give them a try.

现今的配置管理系统都是设计来使并发开发容易的。对他们进行一个尝试吧。

I hope I have not scared you away from concurrent development by explaining the gory details of merging files.  In fact, my goal is quite the opposite.

我希望我没有从解释那些恐怖的关于合并文件的描述中把你从并行开发吓跑。事实上,我的目的是相反的。

Remember that easily-resolved merges are the most common case.  Automerge handles a large percentage of situations with no problems at all.  A large percentage of the remaining cases can be easily handled with a visual merge tool.  The difficult situations are rare, and can still be handled easily by a developer who is patient and careful.

记住:简单解决合并是最常见的情况。自动合并的提交占很大比例的成功。剩下的情况很大比例的也能通过视窗合并工具解决。复杂的情况是很少的,并能够通过开发人员的耐心和细心解决。

Many software teams have discovered that the tradeoff here is worth the trouble.  Concurrent development can bring substantial gains in the productivity of a team.  The extra effort to deal with merge situations is usually a small price to pay.

一些软件团队都发现对于这里的权衡困难是有价值的。并行开发能够为团队带来真正的生产力增长。特别的成就是处理合并的情况通常只需要很低的代价。

Looking Ahead

In the next chapter I will be discussing the concept of a repository in a lot more detail.

 往前看

下一章将更多讨论配置库的概念。

 

posted @ 2005-10-24 21:48  margiex  阅读(2269)  评论(0编辑  收藏  举报