手册

解决冲突

偶尔,当您从存储库更新/合并文件或将工作副本切换到不同的 URL 时,您会遇到 冲突。有两种类型的冲突

文件冲突

如果两个(或更多)开发人员更改了同一个文件的几行,就会发生文件冲突。

树冲突

当一个开发人员移动/重命名/删除了一个文件或文件夹,而另一个开发人员也移动/重命名/删除了该文件或文件夹,或者只是修改了该文件或文件夹时,就会发生树冲突。

文件冲突

当两个或多个开发人员更改了同一个文件的几行时,就会发生文件冲突。由于 Subversion 对您的项目一无所知,因此它将解决冲突的任务留给开发人员。文本文件中冲突区域的标记如下

<<<<<<< filename
your changes
=======
code merged from repository
>>>>>>> revision
      

此外,对于每个冲突文件,Subversion 会在您的目录中放置三个额外的文件

filename.ext.mine

这是您在更新工作副本之前工作副本中存在的文件 - 也就是说,没有冲突标记。此文件包含您最新的更改,除此之外没有其他内容。

filename.ext.rOLDREV

这是您更新工作副本之前的基本修订版本的文件。也就是说,它是您在进行最新编辑之前签出的文件。

filename.ext.rNEWREV

这是您的 Subversion 客户端在您更新工作副本时从服务器接收到的文件。此文件对应于存储库的 HEAD 修订版本。

您可以使用 TortoiseSVN编辑冲突 启动外部合并工具/冲突编辑器,也可以使用任何文本编辑器手动解决冲突。您应该决定代码应该是什么样子,进行必要的更改并保存文件。使用 TortoiseMerge 或其他流行工具等合并工具通常更容易,因为它们通常以 3 窗格视图显示相关文件,您不必担心冲突标记。如果您确实使用文本编辑器,则应搜索以字符串 <<<<<<< 开头的行。

之后执行命令 TortoiseSVN已解决 并将您的修改提交到存储库。请注意,Resolve 命令实际上并没有解决冲突。它只是删除了 filename.ext.minefilename.ext.r* 文件,以允许您提交更改。

如果您与二进制文件发生冲突,Subversion 不会尝试自行合并这些文件。本地文件将保持不变(与您上次更改时的状态完全相同),并且您将拥有 filename.ext.r* 文件。如果您想放弃更改并保留仓库版本,只需使用“还原”命令。如果您想保留您的版本并覆盖仓库版本,请使用“已解决”命令,然后提交您的版本。

如果您右键单击父文件夹并选择 TortoiseSVN已解决...,则可以对多个文件使用“已解决”命令。这将弹出一个对话框,列出该文件夹中所有冲突的文件,您可以选择要标记为已解决的文件。

属性冲突

当两个或多个开发人员更改了相同的属性时,就会发生属性冲突。与文件内容一样,解决冲突只能由开发人员完成。

如果其中一个更改必须覆盖另一个更改,请选择 使用本地属性解决使用远程属性解决 选项。如果更改必须合并,请选择 手动编辑属性,确定属性值应该是什么,然后标记为已解决。

树冲突

当开发人员移动/重命名/删除文件或文件夹时,另一个开发人员也移动/重命名/删除了该文件或文件夹,或者只是修改了该文件或文件夹,就会发生树冲突。导致树冲突的情况有很多,所有这些情况都需要不同的步骤来解决冲突。

当在 Subversion 中本地删除文件时,该文件也会从本地文件系统中删除,因此即使它是树冲突的一部分,它也不能显示冲突覆盖,您也不能右键单击它来解决冲突。请改用 检查修改 对话框来访问 编辑冲突 选项。

TortoiseSVN 可以帮助您找到合并更改的正确位置,但可能需要进行额外的工作才能解决冲突。请记住,更新后,工作 BASE 将始终包含每个项目的修订版本,这些版本是在更新时在仓库中存在的。如果您在更新后还原更改,它将恢复到仓库状态,而不是您开始进行自己的本地更改时的状态。

本地删除,更新时传入编辑

  1. 开发人员 A 修改了 Foo.c 并将其提交到仓库。

  2. 开发人员 B 同时将 Foo.c 移动到 Bar.c 中的工作副本中,或者只是删除了 Foo.c 或其父文件夹。

开发者 B 的工作副本更新导致树冲突

  • Foo.c 已从工作副本中删除,但标记为树冲突。

  • 如果冲突是由于重命名而不是删除导致的,则 Bar.c 被标记为已添加,但不包含开发者 A 的修改。

开发者 B 现在必须选择是否保留开发者 A 的更改。在文件重命名的 경우,他可以将更改合并到重命名的文件 Bar.c 中。对于简单的文件或目录删除,他可以选择保留带有开发者 A 更改的项目并丢弃删除。或者,通过将冲突标记为已解决而不做任何操作,他实际上丢弃了开发者 A 的更改。

冲突编辑对话框提供合并更改的功能,如果它可以找到重命名的 Bar.c 的原始文件。如果有多个文件可能是移动源,则会显示每个文件的按钮,允许您选择正确的文件。

本地编辑,更新时传入删除

  1. 开发者 A 将 Foo.c 移动到 Bar.c 并将其提交到存储库。

  2. 开发者 B 在他的工作副本中修改了 Foo.c

或者在文件夹移动的情况下...

  1. 开发者 A 将父文件夹 FooFolder 移动到 BarFolder 并将其提交到存储库。

  2. 开发者 B 在他的工作副本中修改了 Foo.c

开发者 B 的工作副本更新导致树冲突。对于简单的文件冲突

  • Bar.c 作为普通文件添加到工作副本中。

  • Foo.c 被标记为已添加(带历史记录)并存在树冲突。

对于文件夹冲突

  • BarFolder 作为普通文件夹添加到工作副本中。

  • FooFolder 被标记为已添加(带历史记录)并存在树冲突。

    Foo.c 被标记为已修改。

开发人员 B 现在需要决定是采用开发人员 A 的重组并将她的更改合并到新结构中的相应文件中,还是简单地恢复 A 的更改并保留本地文件。

要将她的本地更改与重组合并,开发人员 B 必须首先找出冲突文件 Foo.c 在存储库中被重命名/移动到的文件名。这可以通过使用日志对话框来完成。然后使用显示正确源文件的按钮来解决冲突。

如果开发人员 B 认为 A 的更改是错误的,那么她必须在冲突编辑器对话框中选择 标记为已解决 按钮。这将标记冲突的文件/文件夹为已解决,但需要手动删除开发人员 A 的更改。同样,日志对话框有助于跟踪移动的内容。

本地删除,更新时传入删除

  1. 开发者 A 将 Foo.c 移动到 Bar.c 并将其提交到存储库。

  2. 开发人员 B 将 Foo.c 移动到 Bix.c

开发者 B 的工作副本更新导致树冲突

  • Bix.c 被标记为带有历史记录的添加。

  • Bar.c 被添加到工作副本中,状态为“正常”。

  • Foo.c 被标记为已删除,并且存在树冲突。

要解决此冲突,开发人员 B 必须找出冲突文件 Foo.c 在存储库中被重命名/移动到的文件名。这可以通过使用日志对话框来完成。

然后开发人员 B 必须决定保留 Foo.c 的哪个新文件名 - 开发人员 A 完成的还是他自己完成的重命名。

在开发人员 B 手动解决冲突后,必须使用冲突编辑器对话框中的按钮将树冲突标记为已解决。

本地缺失,合并时传入编辑

  1. 开发人员 A 在 trunk 上工作,修改了 Foo.c 并将其提交到存储库

  2. 开发人员 B 在分支上工作,将 Foo.c 移动到 Bar.c 并将其提交到存储库

将开发人员 A 的 trunk 更改合并到开发人员 B 的分支工作副本会导致树冲突

  • Bar.c 已经在工作副本中,状态为“正常”。

  • Foo.c 被标记为缺失,并且存在树冲突。

要解决此冲突,开发人员 B 必须在冲突编辑器对话框中将文件标记为已解决,这将将其从冲突列表中删除。然后她必须决定是将缺失的文件 Foo.c 从存储库复制到工作副本,还是将开发人员 A 对 Foo.c 的更改合并到重命名的 Bar.c 中,或者通过将冲突标记为已解决而不做其他操作来忽略这些更改。

请注意,如果您从存储库复制缺失的文件,然后标记为已解决,您的副本将再次被删除。您必须先解决冲突。

本地编辑,合并时传入删除

  1. 开发人员 A 在 trunk 上工作,将 Foo.c 移动到 Bar.c 并将其提交到存储库。

  2. 开发人员 B 在分支上工作,修改了 Foo.c 并将其提交到存储库。

  1. 开发者 A 在主干分支上工作,将父文件夹 FooFolder 移动到 BarFolder 并提交到仓库。

  2. 开发者 B 在分支上工作,修改了工作副本中的 Foo.c 文件。

将开发人员 A 的 trunk 更改合并到开发人员 B 的分支工作副本会导致树冲突

  • Bar.c 被标记为已添加。

  • Foo.c 被标记为已修改,并存在树冲突。

开发人员 B 现在需要决定是采用开发人员 A 的重组并将她的更改合并到新结构中的相应文件中,还是简单地恢复 A 的更改并保留本地文件。

为了将她的本地更改与重组合并,开发者 B 首先需要找出冲突文件 Foo.c 在仓库中被重命名/移动到的文件名。这可以通过使用合并源的日志对话框来完成。冲突编辑器只显示工作副本的日志,因为它不知道合并中使用了哪个路径,因此您需要自己找到它。然后必须手动合并更改,因为目前没有办法自动或简化此过程。一旦更改被移植,冲突的路径就变得多余,可以删除。

如果开发者 B 认为 A 的更改是错误的,那么她必须选择冲突编辑器对话框中的 标记为已解决 按钮。这将标记冲突的文件/文件夹为已解决,但需要手动删除开发者 A 的更改。同样,合并源的日志对话框有助于跟踪移动的内容。

本地删除,合并时传入删除

  1. 开发人员 A 在 trunk 上工作,将 Foo.c 移动到 Bar.c 并将其提交到存储库。

  2. 开发者 B 在分支上工作,将 Foo.c 移动到 Bix.c 并提交到仓库。

将开发人员 A 的 trunk 更改合并到开发人员 B 的分支工作副本会导致树冲突

  • Bix.c 被标记为正常(未修改)状态。

  • Bar.c 被标记为已添加,并带历史记录。

  • Foo.c 被标记为丢失,并存在树冲突。

为了解决此冲突,开发者 B 必须找出冲突文件 Foo.c 在仓库中被重命名/移动到的文件名。这可以通过使用合并源的日志对话框来完成。

然后开发人员 B 必须决定保留 Foo.c 的哪个新文件名 - 开发人员 A 完成的还是他自己完成的重命名。

在开发人员 B 手动解决冲突后,必须使用冲突编辑器对话框中的按钮将树冲突标记为已解决。

其他树冲突

还有其他情况被标记为树冲突,仅仅是因为冲突涉及文件夹而不是文件。例如,如果您在主干分支和分支中都添加了同名文件夹,然后尝试合并,您将遇到树冲突。如果您想保留合并目标中的文件夹,只需将冲突标记为已解决。如果您想使用合并源中的文件夹,则需要先在目标中 SVN 删除该文件夹,然后再次运行合并。如果您需要更复杂的操作,则需要手动解决。

TortoiseSVN 主页