0

开始之前的一个简短说明:“设置舞台”需要很多解释,看起来这更像是一个设计问题,而不是一个关于编程问题的问题。这个问题其实是关于SVN分支和合并的,所以请读到最后。

设想:

我有一个包含很多项目的大型 Visual Studio 解决方案。我用的是SVN,所以主干当然有我开发的生产线。这包括一个核心 DLL 程序集、一个“主”UI 用户客户端和一些“插件”程序集,这些程序集通过在核心程序集上实现接口以在 UI 中提供功能,并且还通过利用一组服务来操作为所有插件提供通用功能的方法(例如持久性逻辑操作、集中式文件存储架构的存储操作等)

在此处输入图像描述

随着时间的推移,我还构建了一些外部实用程序,它们必须复制插件中的许多业务逻辑。我不会详细介绍,因为它最终会分散我的主要问题,而只是想象一下,例如,处理与特定插件数据相关的集中维护操作的服务器上的预定服务。

当我最初构建这个应用程序时,我(愚蠢地)没有预料到需要集中服务层,所以我构建了核心组件(无论好坏),如上所示,与应用程序的表示层紧密集成. 换句话说,将插件与用户界面集成所需的 UI 表示逻辑以及插件执行常见插件逻辑操作所需的业务逻辑都是一个“核心”组件的一部分。因此,插件和集中式服务之间存在的许多“共享”逻辑导致了重复代码。

在此处输入图像描述

我决定进行主要的重构计划,将通用逻辑——与演示无关的逻辑——提取到一个“共享”程序集中。为此,我从主干上创建了一个分支。我将公共代码重新组织为“共享”程序集,并重新指向客户端应用程序(插件等)和外部服务应用程序中的所有内容以利用共享程序集。在许多情况下,我还必须重命名类以适应它们未来更通用的用途。核心组件保留在原位,仅用于代理插件和 UI 之间的表示层职责。

在此处输入图像描述

问题:

现在我已经成功地完成了重构,我想将分支重新集成回主干。即使在简单的情况下,合并也是一件棘手的事情,但我在这里面临的是很多树冲突,委婉地说。此外,除了驻留在一个全新的项目中之外,“共享”项目中的文件夹结构与“核心”项目中的文件夹结构有很大不同。在许多情况下,由于使用共享程序集的新机制,类位于不同的位置。

我想维护每个类的版本历史,从核心程序集中的旧家到共享程序集中的新家。此外,我想保证合并成功。这似乎很明显,但在测试整个场景的微型版本时,我永远无法以我的分支功能保持完整不变的方式解决冲突。此外,正如我之前所说,我已经重命名了一些类以适应它们更一般的角色,这使得维护版本历史变得非常棘手。

我会注意到我正在使用AnkhSVN,当您重命名文件以修复移动时,它有助于“正常”情况,但它似乎不适用于这些主要的树冲突情况。另外,我知道不同版本的 SVN 之间的合并工作方式存在差异——我相信它是 SVN 1.5 之前的版本和 SVN 1.5 之后的版本。我正在使用 SVN 1.9.3。

几个星期以来,我一直试图弄清楚这一点。我一直在翻阅SVN 书籍TortoiseSVN 资源,以及任何我可以从谷歌搜索中找到的东西,比如thisthisthis —— 还有很多很多很多其他的。我觉得我快疯了,我认为高级 SVN(和 Tortoise)不可能用传统的自学、从网络和书籍中学习的方法来学习。无论如何,我将非常感谢那里的任何见解。

当您使用 SVN 创建功能分支并计划进行主要的树更改和“移动”(即重命名)以便您可以将这些更改与主干重新集成而不会丢失任何内容时,正确的方法是什么?

4

1 回答 1

0

恭喜踩到SVN中最“流行”的rake——《重构后的Merge Hell》!

痛苦的经历产生了(至少)两个简单的规则:

  1. 永远不要在 SVN 中进行重构
  2. 如果您忽略规则 1:以世界上所有神圣和美好的事物的名义,在分支重构期间不要触摸主干中的任何东西

如果你拒绝这些正义的圣约,你还有得救的方法

纯SVN方式,又长又脏

合并所有子树,这是树冲突的来源,手动确定每个源和目标,例如

svn merge NEW_PATH/NEW_NAME old_path/old_name

并通过完全合并完成这项血腥的工作

Tricky Mercurial-way(或 Git-way,但我只是讨厌 Git)

前言:对于现代 DVCS 来说,这样的合并根本不是问题,它们有通往 SVN-repos 的“桥梁”,因此 - 您可以将这项合并工作委托给选择的外部 VCS 并返回结果(有一些限制和警告)

我懒得谈论所有的 DVCS 并且只会解释 Mercurial(考虑到使用 SVN 背景,这将是最不痛苦的迁移)。

使用 HGSubversion Mercurial 可以读取(拉)和写入(推送)到 Subversion 存储库,但是 - 它不能推送到它自己的合并结果,因此:它将是多阶段操作,在过程

一个简短的概要

  1. 安装 Mercurial (TortoiseHG) 和 HGSubversion 扩展
  2. 将整个 SVN 存储库克隆到 Mercurial 到某个临时位置(不是当前的 Subversion WC)
  3. 将分支合并到主线(SVN 的主干成为default分支),解决(可能的)上下文冲突(不是树)
  4. 试验结果
  5. 通过 Mercurial 工作目录的内容(分别注意和文件夹)执行Subversion 工作副本(显然是主干的 WC)的完全替换.svn.hg
  6. 将 WC 提交到主干
  7. 为了美观和遵守所有规则,“欺骗”主干的合并信息数据(在步骤 6 中提交的必须我后来称为合并集,尽管形式上不是真的)

高温高压

PS - 现在使用HGVS迁移到 Mercurial似乎并不是一个完全疯狂的想法

于 2016-04-13T02:18:26.683 回答