代码之家  ›  专栏  ›  技术社区  ›  Mike Thompson

在源代码管理系统中处理多个变更集

  •  10
  • Mike Thompson  · 技术社区  · 15 年前

    我有一个相当罕见的源代码管理问题。在这里的示例中,问题是随着性能而发生的,但我怀疑对于许多SCM,特别是分布式SCM,同样的问题也会发生。

    Perfoce支持变更列表(如果愿意,也支持变更集)。变更列表支持两种常用用法:

    1. 提交变更列表时,提交是原子的,因此所有文件都提交了,或者都没有提交。这是大多数人在提到变更列表时谈论的标题功能。

    2. Perfoce支持多个变更列表。基本上,当您签出一个文件时,您会告诉它它属于哪个变更列表。因此,如果你正在开发一个奇特的新电子邮件功能,这需要几个月的工作,并且能赚数百万美元,并且技术支持部门的人来找你一个昨天必须修复的bug,你不必从整个项目的新分支开始。您只需将bugy文件签入新的变更列表,解决问题,签入新的变更列表,然后返回新电子邮件功能的实际工作,就好像什么都没有发生一样。

    在大多数情况下,一切都很好。然而,当你实施电子邮件功能时,你在各地做了无数的更改,特别是在main.h中,而当你着手修复bug时,你发现你必须做的微小更改也在main.h中。新功能的更改列表已经有main.h签出了,因此你不能轻易地将它在错误修复的变更列表中。

    现在你做什么?您有几个选择:

    1. 创建新的客户机规范。performce中的clientspec是仓库中文件/目录的列表,也是要复制所有内容的本地目标。因此,您可以在不更改电子邮件功能的情况下创建项目的第二个副本。

    2. 做一个软糖。备份main.h的修改副本并还原此文件。然后您可以自由地将main.h签入错误修复更改列表。修复错误,签入错误修复更改列表,然后签出main.h到电子邮件功能更改列表。最后,从一开始所做的备份中合并所有更改。

    3. 您确定您对main.h所做的所有更改都没有副作用或依赖性,所以您只需将main.h移到bugfix更改列表中,进行更改并签入即可。然后您可以在电子邮件功能更改列表中再次查看它。显然,这种方法有两个问题:第一,事实上可能存在你没有考虑到的副作用,第二,你已经破坏了你的版本历史。

    选项1可能是最干净的,但并不总是实用的。我正在研究的一个项目有数百万行代码和一个非常复杂的构建过程。建立一个新的环境需要一天的时间,所以5分钟的错误修复并不是很实际。

    选项3是一个不好的选项,但它是最快的,所以它可能非常诱人。

    这就剩下了选项2,也就是我通常使用的选项。

    有人有更好的解决方案吗?

    我为这个冗长的问题道歉,但我在StackOverflow上发现,充分考虑问题可以得到更好的答案。

    8 回复  |  直到 8 年前
        1
  •  7
  •   Greg Hewgill    15 年前

    这个确切的问题被称为“纠结的工作拷贝问题”。Ryan Tomayko有一篇题为 The Thing About Git 这就详细讨论了这个问题,以及Git如何解决它。

    这是关于Git最好的事情之一。我用 git add -p 至少每天,帮助提交独立于彼此有意义的代码块。两个逻辑上不同的变更在同一个源文件中已经变得不相关了。

        2
  •  3
  •   John Stauffer    15 年前

    我从一开始就通过维护多个工作区来通过性能来管理这一点。我的主要开发是在主线上(新开发发生的地方),而另一个则指向已发布代码的分支。如果我需要修复一个bug,我将转到发布分支。

    我不确定这是否适用于您,但至少您不需要在每次修复bug时创建一个新的工作区(因为它已经存在)。

        3
  •  2
  •   Community prosti    7 年前

    ClearCase还支持changelist(在其UCM风格中称为“活动”),并提出了类似的挑战。

    只有当您确定“调试工作”与当前的开发工作(电子邮件功能)不兼容并且最好保存在单独的分支中时,选项1(“分支类型”)才有意义。然后,您可以将在“补丁”分支中所做的任何更正更新到主分支(因为并非所有要修复的bug都必须同时存在于这两个分支中:当前的开发可能会使某些修复过时)。
    也见“ What is a branch “,你的是什么? merge workflow .

    选项3说明了变更集概念的局限性:文件的单个修订版(或“版本”)只能是 一次更改集。

    这个 git add -p (添加补丁) mentioned by Greg 是选项1和选项3的替代,因为它利用了“索引”(分段区域)的分段功能,您可以在该区域中决定实际提交的内容以及保留在您的私人空间中的内容。
    这很好,但在我的经验中,很难在很长一段时间内保持下去,特别是在一组通用的文件上,您可以应用两种不同的演进。分支更干净,单元测试更简单。然而,对于像你提到的一个小修复,这可能是一个很好的出路。

    选项2是一个实际的解决方案,当你意识到你对两个不同的努力有两个改变时(仍然是兼容的,不会“打破”彼此)。
    但可能更简单的解决方案是:

    • 在电子邮件中签入main.h的当前状态,
    • 签入Bug,修复它,签入Bug
    • 然后在电子邮件中签出以恢复电子邮件功能开发。

    同样,如果这两个开发工作(电子邮件和bug)是兼容的,那么您可以有一个混合活动的修订历史。

        4
  •  2
  •   Douglas Leeder    15 年前

    我们使用作业以便单个“任务”可以跨越多个已提交的变更集。

    因此:

    1. check main.h更改独立于其他更改
    2. 签入主.h的当前状态-在长期电子邮件作业下
    3. 对main.h进行错误修复
    4. 签入错误修复变更集
    5. 如果需要,在电子邮件作业下编辑main.h
        5
  •  2
  •   ChrisF PerfectlyRock    15 年前

    您没有提到选项4,即创建分支。

    您可以拥有不进行任何单独更改的主代码行,只需集成其他分支。

    然后,您就有了主要的开发线,在这里您正在创建您的奇特的新电子邮件功能。这是你大部分工作的地方。

    最后你有了错误修复分支。这是你做所有小编辑和紧急错误修复的地方。一旦这些测试完成,它们就会集成到用于QA和发布的主代码行中(应该在单独的分支上)。然后可以将这些编辑从主线集成到开发线中,这样您就可以一直使用最新的代码。这种集成可以在您选择的时间发生,这样您就可以确信它不会在新代码中造成任何问题。

    这是最好的解决办法。

        6
  •  1
  •   Mark James    15 年前

    为了提高性能,您可以使用p4 tar之类的工具:

    http://public.perforce.com/wiki/P4tar

    它允许您保存和恢复当前的变更列表,进行修复,然后恢复您的工作。您仍然需要将更改集成到main.h中,但这会使任务更容易完成。

        7
  •  1
  •   Community prosti    7 年前

    我同意 ChrisF :分支将是最自然的解决方案。

    我使用Perfoce已有一段时间了,它确实没有其他scm那样强大的分支能力,但它是可以做到的。

    诀窍很简单:为你正在做的每一项任务创建一个分支(上帝啊 branch per task pattern )切换到它。如果你需要修理其他东西怎么办?很简单,只需在签入所有内容(使用一些SCM,您甚至不需要签入)后切换到其他分支即可修复它,稍后返回到原始的“电子邮件”分支。

        8
  •  1
  •   Sebastian K    8 年前

    我认为解决表演中“混乱的工作拷贝”问题的方法是 shelving

    您可以使用它的命令行,如下所示:

    P4搁架-C 123

    我通常在IDE插件(Visual Studio或Eclipse)或P4V中使用它。当您搁置文件时,您可以选择是否要还原文件,基本上是为您的紧急工作准备一份干净的工作。然后,当您完成返回中断的工作时,您可以取消搁置这些文件。

    如果您使用的是命令行,则可以创建一个简单的脚本,该脚本将同时保存在所选变更列表中,并且如果成功地还原了所选变更列表中的更改,则会给您一个干净的记录:

    P4搁置-C$1&P4还原-C$1//仓库/您的/分支机构/…

    只需使用变更列表编号作为参数来调用它。相反,当你完成了你的其他工作,你可以从你的架子上取下你的文件,然后按如下方式取下架子,这基本上就是你的出发点:

    P4取消搁置-C$1-F-S$1&P4搁置-C$1-D