解决 SVN 二进制冲突

6
我正在与其他开发人员一起为一个项目使用svn进行源代码控制。虽然svn在源代码控制方面工作得很好,但我们总是在提交dll文件时遇到冲突。
当我解决冲突时(由于diff程序无法处理二进制文件,所以删除了我的dll文件),我必须重新构建才能提交。那么,你应该如何解决这种冲突呢?
编辑:
由于该项目是游戏修改版,非程序员也需要访问最新版本,因此dll文件位于单独的svn文件夹中。

你是否有实际需要将DLL文件放在SVN中的特定需求? - Beau Simensen
7个回答

8
如其他答案中所提到的:首先,您不应该对生成的dll进行版本控制。但如果您真的必须对它们进行版本控制,则可以在不使用差异工具删除dll文件的情况下解决冲突:
对于每个有冲突的文件,Subversion会在您的工作副本中放置三个额外的未版本化文件:
filename.mine 这是您在更新工作副本之前存在的文件,即没有冲突标记的文件。此文件中仅包含您最新的更改。(如果Subversion认为该文件无法合并,则不会创建.mine文件,因为它将与工作文件相同。)
filename.rOLDREV
这是您更新工作副本之前的基本修订版本的文件。也就是说,在进行最新编辑之前检出的文件。
filename.rNEWREV
这是您的Subversion客户端在更新工作副本时刚从服务器接收到的文件。此文件对应于存储库的HEAD修订版本。
其中,OLDREV是.svn目录中文件的修订号,NEWREV是存储库HEAD的修订号。
现在,要解决这样的冲突,请删除您不需要的其他文件:
- 如果您想保留自己的dll,请删除文件filename.rOLDREV、filename.rNEWREV。 - 如果您想保留来自存储库的dll,请删除文件filename.rOLDREV和filename.mine,然后将filename.rNEWREV复制到filename中。
完成后,执行:
svn resolved filename

告诉Subversion你已经自己解决了冲突。

我认为这就是我想要的(下次将不得不尝试一下),因为我不知道如果你没有破坏svn,是否可以删除你不想要的那个。 - Lodle
你不能用svn客户端提供的工具“破坏svn”。最多只能在源代码树中引入混乱。 - user3850

7

如果你正在构建一个DLL(而不是没有源代码的外部DLL),那么源代码应该在源代码控制中,而不是二进制文件。

如果你不想将其包含在特定的存储库中,那么可以将其作为svn:external包含。


我有一些二进制文件需要在我的某些代码库中引用。它们通常不会经常更改,而且我通常会在多个项目之间共享它们,因此我只需使用外部存储库即可。 - Dana Robinson

4
对于二进制文件,大多数情况下,您希望接受其中任何一个版本。例如,如果所讨论的文件是可执行工具,则通常一个版本可能比另一个版本更新,而这可能是您想使用的版本。
(当然,并非总是如此,SVN无法知道这一点。基本上,您必须知道发生了什么变化,如果不知道,请与其他进行更改的人交谈,就像在项目中合作时一样)
要接受从中合并的分支中的版本,请使用:
svn resolve --accept=theirs-full path/to/filename

要接受之前在当前分支中的版本,请使用:

svn resolve --accept=mine-full path/to/filename

有时,SVN会拒绝使用 theirs-full 并显示警告:
svn: warning: W195024: Inapplicable conflict resolution option given for conflicted path

例如,如果文件在本地被修改("mine")并在远程被删除("theirs"),就会发生这种情况。在这种情况下,你必须执行以下操作之一:
1. 使用svn rm path/to/filename命令删除文件(接受“their”的更改,即删除文件)。
2. 手动复制文件,如已接受答案中所述的方法https://dev59.com/_kbRa4cB1Zd3GeqPxiIA#410767,而不是使用旨在完成你要完成的任务的命令行选项。
如果你知道两个文件是相同的(但 SVN 仍将它们标记为冲突,原因已经说明),你还可以使用以下命令:
svn resolve --accept=working path/to/filename

在相同文件的情况下,这与所有其他命令基本相同,但SVN不会胆怯地拒绝执行它。


似乎对于“本地文件编辑、传入文件删除或合并时移动” 冲突,svn resolve --accept theirs-full 也会出现 W195024 错误。删除文件,然后接受 working 似乎可以解决问题。谢谢。 - TBBle
跟进:我还必须使用 svn rm 命令将它们删除,因为在前两个步骤之后,它们似乎被留下来了,而不是被删除了。 - TBBle
1
@TBBle 感谢您澄清这一点。我还注意到您在我没有给出任何解释的情况下使用了“also”这个词,只是说“SVN是一个(请原谅我的法语)”:D。我会编辑我的帖子。必须使用svn rm而不是仅删除文件与常见的SVN行为一致。您必须明确告诉SVN您要删除某些内容。 - Florian Winter

4
通常情况下,您不会在源代码控制中存储自己编译的DLL。您是否有特定原因需要这样做?
我设置了我的开发环境,使任何人都可以独立构建我的项目组件。这样,我的源代码控制系统中只有我的源代码。这有很多好处:
- 当尝试检入DLL或EXE时,可以避免二进制文件冲突 - 源代码控制系统跟踪的数据量更小,速度更快 - 当开发人员始终构建自己的DLL时,他们可以合理地确定他们拥有的源代码与编译后的文件匹配。如果使用其他人构建的内容,则永远无法确定。
正如在评论中提到的那样,将第三方DLL存储在源代码控制系统中是完全合理的,特别是如果您实际上没有它们的源代码。我还曾参与过存储各种开放源代码库的分发文件(.tar.gz等)的项目,在构建所有目标中,我们使用了一整套Makefile来构建这些库。

1
我认为将DLL包含在源代码控制中是可以的,但仅限于第三方库的DLL,而不是你自己的源代码。例如,我会将NUnit二进制文件包含在源代码控制中,而不是每次都将源代码放在那里并重新编译。 - Jon Skeet
每次提交dll时都会出现冲突。我认为他不是指第三方库。你不应该总是提交第三方库...更不用说会出现冲突了。 - R. Martinho Fernandes
@Martinho:当然。我仅对“通常情况下,您根本不会在源代码控制中存储DLL”这一说法提出异议。我认为Greg应该澄清一下。 - Jon Skeet
@Jon Skeet:我更新了我的回答,以澄清我的意思。当然,我的回答是基于我对原始问题的理解(其中“the dlls”指的是“我刚刚构建的二进制文件”)的背景下给出的。 - Greg Hewgill

2

在版本控制中也有二进制文件是合理的:

  • 它避免了只使用二进制文件的人重新构建的麻烦。

  • 当您发布时,二进制文件已经固定。

为了使这个工作起来,二进制文件需要始终对应于源代码。 因此,如果您合并了源代码,您需要从中重新构建二进制文件, 从合并版本中选择一个二进制文件是不行的。


1
同意,如果你和非程序员一起开发项目,将二进制文件放入源代码控制中是有意义的。 - driAn
3
好的建议,或许是SVN行为背后的原理,但并不是解决问题的方法。 - Matthew Read

0

请确保您的dll文件设置了svn:mime-type属性,值为application/octet-stream或其他非文本类型。

svn propget *.dll
svn propset svn:mime-type application/octet-stream *.dll

当冲突发生时,您仍然需要实际解决它们。

并查看文档的 文件内容类型 章节。


0

如果您将*.dll文件放在单独的文件夹中,那么按照以下步骤操作会更容易:

  1. 在构建更改之前,直接更新*.dll文件夹,最好也更新源代码,如果您相信您的同事只提交可编译的源代码。(如果出现冲突(这时候是您的错,因为您在更新到最新版本之前已经更改了某些内容))
  2. 进行构建。
  3. 直接提交结果。

或者:

不要构建到目录中的路径,而是构建到外部某个地方,直到您对结果满意为止。

然后按照以下步骤操作:

  1. 更新dlls文件夹的工作副本(如果有任何冲突,那就是您的错,并通过“保留他们”的方式解决冲突)
  2. 将您的工作.dll文件复制到工作副本中
  3. 通知您的同事您将提交一个新版本(您可以跳过此步骤)
  4. 提交您的工作,如果有任何冲突,那应该是他们的错。

现在您有两种可能性:

5a. 如果您是一个非常讨厌的人,可以通过保留我的方式来解决问题。

5b. 你应该按照正常的方式工作...阅读日志文件,找出在你将工作复制到文件夹并提交时,在短时间内也进行了提交的同事。与该同事交谈,并商定进一步的行动方案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接