有时,当您从版本库更新/合并文件,或者当您将工作副本切换到不同的 URL 时,您会遇到冲突。冲突有两种类型
当两个(或多个)开发者修改了文件的相同几行时,会发生文件冲突。
当一个开发者移动/重命名/删除文件或文件夹,而另一个开发者也移动/重命名/删除或仅仅修改了该文件或文件夹时,会发生树冲突。
当两个或多个开发者修改了文件的相同几行时,会发生文件冲突。由于 Subversion 对您的项目一无所知,因此它将解决冲突的任务留给了开发者。文本文件中的冲突区域会像这样标记
<<<<<<< filename your changes ======= code merged from repository >>>>>>> revision
此外,对于每个冲突文件,Subversion 会在您的目录中放置三个额外的文件
这是您在更新工作副本之前,工作副本中存在的文件 - 也就是没有冲突标记的文件。此文件包含您的最新更改,没有其他内容。
这是您更新工作副本之前的 BASE 修订版本的文件。也就是说,这是您在进行最新编辑之前检出的文件。
这是您的 Subversion 客户端在您更新工作副本时刚从服务器接收的文件。此文件对应于版本库的 HEAD 修订版本。
您可以使用外部合并工具/冲突编辑器通过 <<<<<<<
开头的行。
之后,执行命令 filename.ext.mine
和 filename.ext.r*
文件,以便您可以提交更改。
如果您有二进制文件冲突,Subversion 不会尝试自行合并文件。本地文件保持不变(与您上次更改时完全一样),并且您有 filename.ext.r*
文件。如果您想放弃您的更改并保留版本库版本,只需使用“还原”命令。如果您想保留您的版本并覆盖版本库版本,请使用“已解决”命令,然后提交您的版本。
如果您右键单击父文件夹并选择
→ ,则可以对多个文件使用“已解决”命令。这将弹出一个对话框,列出该文件夹中的所有冲突文件,您可以选择要标记为已解决的文件。当两个或多个开发者修改了相同的属性时,会发生属性冲突。与文件内容一样,解决冲突只能由开发者完成。
如果其中一个更改必须覆盖另一个更改,则选择 使用本地属性解决 或 使用远程属性解决 选项。如果更改必须合并,则选择 手动编辑属性,整理出属性值应该是什么,并标记为已解决。
当一个开发者移动/重命名/删除文件或文件夹,而另一个开发者也移动/重命名/删除或仅仅修改了该文件或文件夹时,会发生树冲突。有许多不同的情况可能导致树冲突,所有这些情况都需要不同的步骤来解决冲突。
当文件在 Subversion 中本地删除时,该文件也会从本地文件系统中删除,因此即使它是树冲突的一部分,它也无法显示冲突覆盖,并且您无法右键单击它来解决冲突。请改用 检查修改 对话框来访问 编辑冲突 选项。
TortoiseSVN 可以帮助找到合并更改的正确位置,但可能需要额外的操作来解决冲突。请记住,在更新后,工作 BASE 将始终包含每个项目在更新时在版本库中的修订版本。如果您在更新后还原更改,它将返回到版本库状态,而不是返回到您开始进行本地更改时的状态。
开发者 A 修改了 Foo.c
并将其提交到版本库。
开发者 B 同时在他的工作副本中将 Foo.c
移动到 Bar.c
,或者只是删除了 Foo.c
或其父文件夹。
开发者 B 的工作副本更新会导致树冲突
Foo.c
已从工作副本中删除,但标记为树冲突。
如果冲突是由重命名而不是删除引起的,则 Bar.c
被标记为已添加,但不包含开发者 A 的修改。
开发者 B 现在必须选择是否保留开发者 A 的更改。在文件重命名的情况下,他可以将 Foo.c
的更改合并到重命名的文件 Bar.c
中。对于简单的文件或目录删除,他可以选择保留包含开发者 A 更改的项目并放弃删除。或者,通过在不执行任何操作的情况下将冲突标记为已解决,他实际上放弃了开发者 A 的更改。
如果冲突编辑对话框可以找到重命名的 Bar.c
的原始文件,它会提供合并更改的选项。如果有多个文件可能是移动源,则会显示每个文件的按钮,允许您选择正确的文件。
开发者 A 将 Foo.c
移动到 Bar.c
并将其提交到版本库。
开发者 B 修改了他的工作副本中的 Foo.c
。
或者在文件夹移动的情况下...
开发者 A 将父文件夹 FooFolder
移动到 BarFolder
并将其提交到版本库。
开发者 B 修改了他的工作副本中的 Foo.c
。
开发者 B 的工作副本更新会导致树冲突。对于简单的文件冲突
Bar.c
作为普通文件添加到工作副本中。
Foo.c
被标记为已添加(带有历史记录)并具有树冲突。
对于文件夹冲突
BarFolder
作为普通文件夹添加到工作副本中。
FooFolder
被标记为已添加(带有历史记录)并具有树冲突。
Foo.c
被标记为已修改。
开发者 B 现在必须决定是接受开发者 A 的重组并将她的更改合并到新结构中的相应文件中,还是仅仅还原 A 的更改并保留本地文件。
要将她的本地更改与重新组织合并,开发者 B 必须首先找出冲突文件 Foo.c
在版本库中被重命名/移动到哪个文件名。这可以通过使用日志对话框来完成。然后使用显示正确源文件的按钮来解决冲突。
如果开发者 B 认为 A 的更改是错误的,那么她必须在冲突编辑器对话框中选择 标记为已解决 按钮。这会将冲突文件/文件夹标记为已解决,但开发者 A 的更改需要手动删除。同样,日志对话框有助于跟踪移动的内容。
开发者 A 将 Foo.c
移动到 Bar.c
并将其提交到版本库。
开发者 B 将 Foo.c
移动到 Bix.c
。
开发者 B 的工作副本更新会导致树冲突
Bix.c
被标记为已添加并带有历史记录。
Bar.c
以“正常”状态添加到工作副本中。
Foo.c
被标记为已删除并具有树冲突。
要解决此冲突,开发者 B 必须找出冲突文件 Foo.c
在版本库中被重命名/移动到哪个文件名。这可以通过使用日志对话框来完成。
然后开发者 B 必须决定保留 Foo.c
的哪个新文件名 - 开发者 A 完成的还是他自己完成的重命名。
在开发者 B 手动解决冲突后,必须使用冲突编辑器对话框中的按钮将树冲突标记为已解决。
在主干上工作的开发者 A 修改了 Foo.c
并将其提交到版本库
在分支上工作的开发者 B 将 Foo.c
移动到 Bar.c
并将其提交到版本库
将开发者 A 的主干更改合并到开发者 B 的分支工作副本会导致树冲突
Bar.c
已经在工作副本中,状态为“正常”。
Foo.c
被标记为丢失并具有树冲突。
要解决此冲突,开发者 B 必须在冲突编辑器对话框中将文件标记为已解决,这将从冲突列表中删除它。然后她必须决定是否将丢失的文件 Foo.c
从版本库复制到工作副本,是否将开发者 A 对 Foo.c
的更改合并到重命名的 Bar.c
中,或者是否通过将冲突标记为已解决并且不执行其他任何操作来忽略更改。
请注意,如果您从版本库复制丢失的文件,然后标记为已解决,您的副本将再次被删除。您必须先解决冲突。
在主干上工作的开发者 A 将 Foo.c
移动到 Bar.c
并将其提交到版本库。
在分支上工作的开发者 B 修改了 Foo.c
并将其提交到版本库。
在主干上工作的开发者 A 将父文件夹 FooFolder
移动到 BarFolder
并将其提交到版本库。
在分支上工作的开发者 B 修改了她的工作副本中的 Foo.c
。
将开发者 A 的主干更改合并到开发者 B 的分支工作副本会导致树冲突
Bar.c
被标记为已添加。
Foo.c
被标记为已修改并具有树冲突。
开发者 B 现在必须决定是接受开发者 A 的重组并将她的更改合并到新结构中的相应文件中,还是仅仅还原 A 的更改并保留本地文件。
要将她的本地更改与重新组织合并,开发者 B 必须首先找出冲突文件 Foo.c
在版本库中被重命名/移动到哪个文件名。这可以通过使用合并源的日志对话框来完成。冲突编辑器仅显示工作副本的日志,因为它不知道合并中使用了哪个路径,因此您必须自己找到该路径。然后必须手动合并更改,因为目前没有自动化甚至简化此过程的方法。一旦更改被移植过来,冲突的路径就是多余的,可以删除。
如果开发者 B 认为 A 的更改是错误的,那么她必须在冲突编辑器对话框中选择 标记为已解决 按钮。这会将冲突文件/文件夹标记为已解决,但开发者 A 的更改需要手动删除。同样,合并源的日志对话框有助于跟踪移动的内容。
在主干上工作的开发者 A 将 Foo.c
移动到 Bar.c
并将其提交到版本库。
在分支上工作的开发者 B 将 Foo.c
移动到 Bix.c
并将其提交到版本库。
将开发者 A 的主干更改合并到开发者 B 的分支工作副本会导致树冲突
Bix.c
被标记为正常(未修改)状态。
Bar.c
被标记为已添加并带有历史记录。
Foo.c
被标记为丢失并具有树冲突。
要解决此冲突,开发者 B 必须找出冲突文件 Foo.c
在版本库中被重命名/移动到哪个文件名。这可以通过使用合并源的日志对话框来完成。
然后开发者 B 必须决定保留 Foo.c
的哪个新文件名 - 开发者 A 完成的还是他自己完成的重命名。
在开发者 B 手动解决冲突后,必须使用冲突编辑器对话框中的按钮将树冲突标记为已解决。