偶尔,当您从存储库更新/合并文件或将工作副本切换到不同的 URL 时,您会遇到 冲突。有两种类型的冲突
如果两个(或更多)开发人员更改了同一个文件的几行,就会发生文件冲突。
当一个开发人员移动/重命名/删除了一个文件或文件夹,而另一个开发人员也移动/重命名/删除了该文件或文件夹,或者只是修改了该文件或文件夹时,就会发生树冲突。
当两个或多个开发人员更改了同一个文件的几行时,就会发生文件冲突。由于 Subversion 对您的项目一无所知,因此它将解决冲突的任务留给开发人员。文本文件中冲突区域的标记如下
<<<<<<< filename your changes ======= code merged from repository >>>>>>> revision
此外,对于每个冲突文件,Subversion 会在您的目录中放置三个额外的文件
这是您在更新工作副本之前工作副本中存在的文件 - 也就是说,没有冲突标记。此文件包含您最新的更改,除此之外没有其他内容。
这是您更新工作副本之前的基本修订版本的文件。也就是说,它是您在进行最新编辑之前签出的文件。
这是您的 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 的更改。在文件重命名的 경우,他可以将更改合并到重命名的文件 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 在 trunk 上工作,修改了 Foo.c
并将其提交到存储库
开发人员 B 在分支上工作,将 Foo.c
移动到 Bar.c
并将其提交到存储库
将开发人员 A 的 trunk 更改合并到开发人员 B 的分支工作副本会导致树冲突
Bar.c
已经在工作副本中,状态为“正常”。
Foo.c
被标记为缺失,并且存在树冲突。
要解决此冲突,开发人员 B 必须在冲突编辑器对话框中将文件标记为已解决,这将将其从冲突列表中删除。然后她必须决定是将缺失的文件 Foo.c
从存储库复制到工作副本,还是将开发人员 A 对 Foo.c
的更改合并到重命名的 Bar.c
中,或者通过将冲突标记为已解决而不做其他操作来忽略这些更改。
请注意,如果您从存储库复制缺失的文件,然后标记为已解决,您的副本将再次被删除。您必须先解决冲突。
开发人员 A 在 trunk 上工作,将 Foo.c
移动到 Bar.c
并将其提交到存储库。
开发人员 B 在分支上工作,修改了 Foo.c
并将其提交到存储库。
开发者 A 在主干分支上工作,将父文件夹 FooFolder
移动到 BarFolder
并提交到仓库。
开发者 B 在分支上工作,修改了工作副本中的 Foo.c
文件。
将开发人员 A 的 trunk 更改合并到开发人员 B 的分支工作副本会导致树冲突
Bar.c
被标记为已添加。
Foo.c
被标记为已修改,并存在树冲突。
开发人员 B 现在需要决定是采用开发人员 A 的重组并将她的更改合并到新结构中的相应文件中,还是简单地恢复 A 的更改并保留本地文件。
为了将她的本地更改与重组合并,开发者 B 首先需要找出冲突文件 Foo.c
在仓库中被重命名/移动到的文件名。这可以通过使用合并源的日志对话框来完成。冲突编辑器只显示工作副本的日志,因为它不知道合并中使用了哪个路径,因此您需要自己找到它。然后必须手动合并更改,因为目前没有办法自动或简化此过程。一旦更改被移植,冲突的路径就变得多余,可以删除。
如果开发者 B 认为 A 的更改是错误的,那么她必须选择冲突编辑器对话框中的 标记为已解决 按钮。这将标记冲突的文件/文件夹为已解决,但需要手动删除开发者 A 的更改。同样,合并源的日志对话框有助于跟踪移动的内容。
开发人员 A 在 trunk 上工作,将 Foo.c
移动到 Bar.c
并将其提交到存储库。
开发者 B 在分支上工作,将 Foo.c
移动到 Bix.c
并提交到仓库。
将开发人员 A 的 trunk 更改合并到开发人员 B 的分支工作副本会导致树冲突
Bix.c
被标记为正常(未修改)状态。
Bar.c
被标记为已添加,并带历史记录。
Foo.c
被标记为丢失,并存在树冲突。
为了解决此冲突,开发者 B 必须找出冲突文件 Foo.c
在仓库中被重命名/移动到的文件名。这可以通过使用合并源的日志对话框来完成。
然后开发人员 B 必须决定保留 Foo.c
的哪个新文件名 - 开发人员 A 完成的还是他自己完成的重命名。
在开发人员 B 手动解决冲突后,必须使用冲突编辑器对话框中的按钮将树冲突标记为已解决。