我有一个相当罕见的源控制问题。在这里的示例中,Perforce出现了问题,但我怀疑许多SCM会出现同样的问题,尤其是分布式SCM。
Perforce支持更改列表(如果您愿意,还支持更改集)。变更列表支持两种常见用法:
提交更改列表时,提交是原子的,以便提交所有文件或不提交任何文件。这是大多数人在提到变更列表时所谈论的标题功能。
Perforce支持多个更改列表。基本上,当您签出文件时,您告诉它它属于哪个更改列表。所以,如果你正在开发一个花哨的新电子邮件功能,它需要花费数月的时间才能完成数百万美元,并且有人从技术支持中找到了一个必须在昨天修复的bug,你不必从头开始整个项目的新分支。您可以将错误文件检入新的更改列表,修复问题,检查新的更改列表并返回新电子邮件功能的实际工作,就好像什么都没发生一样。
在大多数情况下,一切都很好。但是,当您实现电子邮件功能时,您正在整个地方进行数以万计的更改,尤其是在main.h中,并且恰好在开始修复错误时,您会发现您必须进行的微小更改也在main.h.新功能的更改列表已经检出main.h,因此您无法轻松将其放入更改列表中以进行错误修复。
现在你做什么?你有几个选择:
创建新的clientspec。 Perforce中的clientspec是库中的文件/目录列表,以及要复制所有内容的本地目标。因此,您可以创建项目的第二个副本,而无需对电子邮件功能进行任何更改。
做一个软糖。备份修改后的main.h副本并还原此文件。然后,您可以自由地将main.h签入bugfix更改列表。您修复了该错误,检查错误修正更改列表,然后将main.h签出到电子邮件功能更改列表中。最后,您将从一开始的备份中合并所有更改。
您确定您对main.h所做的所有更改都没有副作用或依赖项,因此您只需将main.h移动到bugfix更改列表中,进行更改并将其签入。然后检查它再次进入电子邮件功能更改列表。显然,这种方法存在两个问题:首先,实际上可能存在您未考虑过的副作用,其次是您的版本组织已损坏。
选项1可能是最干净的,但并不总是实用的。我正在开发的一个项目有数百万行代码和一个非常复杂的构建过程。设置新环境需要一天时间,因此对于5分钟的错误修复来说实际上并不实际。
选项3是一个不好的选择,但它是最快的,所以它可以非常诱人。
留下选项2,这是我通常使用的选项。
有人有更好的解决方案吗?
我对这个冗长的问题表示道歉,但我在StackOverflow上发现,充分考虑问题可以得到更好的答案。
答案 0 :(得分:7)
这个确切的问题被称为“纠结的工作副本问题”。 Ryan Tomayko有一篇名为The Thing About Git的博客文章详细讨论了这个问题以及Git如何解决这个问题。
这是关于Git的最好的事情之一。我至少每天使用git add -p
来帮助提交彼此独立的各个代码块。两个逻辑上不同的更改在同一源文件中的事实变得无关紧要。
答案 1 :(得分:3)
我通过从一开始就维护多个工作区来管理Perforce。我的主要开发是在主线上(新开发发生的地方),而另一个是指向已发布代码的一个分支。如果我需要修复错误,我会去发布分支。
我不确定这是否适合您,但至少每次修复错误时都不需要创建新的工作区(因为它已经存在)。
答案 2 :(得分:2)
ClearCase也支持更改列表(在其UCM风格中称为“活动”),并提出类似的挑战。
选项1(“分支类型”)仅在您确定“调试工作量”与当前开发工作(电子邮件功能)不兼容时才有意义,并且最好保存在单独的分支中。然后你可以改进在“补丁”分支中对主分支所做的任何修正(因为不是你要修复的每个错误都必须存在于两者中:当前的开发可能会使一些修复过时)。
另请参阅“What is a branch”,以及您的merge workflow。
选项3说明了变更集概念的限制:文件的单个修订版(或“版本”)一次只能是一个变更集的一部分。
git add -p
(添加补丁)mentioned by Greg是选项1和3的替代,因为它利用了“索引”(暂存区)的分段功能,您决定使用的区域什么将实际承诺,以及将留在你的私人空间
这很好,但在我的经验中很难长时间维持,特别是在你应用两种不同演变的一组通用文件上。分支更清洁,更易于单元测试。但是,对于像你提到的小修理,它可能是一个很好的出路。
选项2是实用的解决方案,当您意识到您有两个不同的努力(仍然是兼容的,彼此没有“破坏”)的两个更改。
但可能更简单的解决方案就是:
同样,如果两个开发工作(电子邮件和错误)兼容,您可以拥有混合活动的修订历史记录。
答案 3 :(得分:2)
我们使用作业,以便单个“任务”可以跨越多个已提交的更改集。
因此:
答案 4 :(得分:2)
您没有提及选项4,即创建分支。
您可以拥有未进行任何更改的主代码行 - 只需从其他分支进行集成。
然后您将拥有主要开发线,您可以在其中创建新的电子邮件功能。这是你完成大部分工作的地方。
最后你有bug修复分支。这是您进行所有次要编辑和紧急错误修复的地方。一旦经过测试,它们就会集成到QA和发布的主代码行中(应该在一个单独的分支上)。然后可以将这些编辑从主线集成到您的开发线中,以便您始终使用最新的代码。这种集成可以在您选择时进行 - 这样您就可以确信它不会在您的新代码中造成任何问题。
这是(IMO)最好的解决方案。
答案 5 :(得分:1)
对于Perforce,您可以使用类似p4 tar的工具:
http://public.perforce.com/wiki/P4tar
它可让您保存并还原当前的更改列表,进行修复,然后还原您的工作。您仍然需要将更改集成到main.h,但它使任务更容易。
答案 6 :(得分:1)
我同意ChrisF:分支将是最自然的解决方案。
我已经使用了Perforce一段时间,而且它的分支与其他SCM一样强大,但它可以做到。
诀窍很简单:为你正在处理的每个任务创建一个分支(上帝branch per task pattern),切换到它。如果您需要修复其他内容怎么办?检查完所有内容(使用一些甚至不需要签入的scms)后,只需切换到另一个分支即可修复它,然后再回到原来的“电子邮件”分支。
答案 7 :(得分:1)
我认为Perforce中“纠结工作副本”问题的解决方案是shelving
您可以按如下方式使用命令行:
p4 shelve -c 123
我通常在IDE插件(Visual Studio或Eclipse)或P4V中使用它。当你搁置时,你可以选择是否要恢复你的文件,基本上为你的紧急工作得到一个干净的名单。然后,当你完成回到被打断的工作时,你可以取消搁置文件。
如果您使用的是命令行,那么您可以创建一个简单的脚本,该脚本既可以保存,也可以成功还原所选更改列表中的更改,为您提供一个清晰的平台:
p4 shelve -c $ 1&& p4 revert -c $ 1 // depot / your / branch /...
只需使用更改列表编号作为参数调用它。相反,当您完成其他工作后,您可以从架子上获取文件并按照以下方式移除架子,这基本上将您带到起点:
p4 unshelve -c $ 1 -f -s $ 1&& p4搁置-c $ 1 -d