自动还原失败的提交


43

我的一位同事告诉我,他正在考虑使我们的CI服务器还原失败构建的提交,因此HEADin master始终是稳定的(至少在通过构建时如此)。

这是最佳实践master吗?还是比在开发人员修复它之前让它崩溃更成问题?

我的想法是,还原提交会使读取提交和修复的任务变得更加复杂(开发人员必须先还原还原,然后提交修复,这也会使混乱git log),我们应该离开提交然后提交固定。尽管我看到了master稳定的优点,但是这种失败提交的还原并不能说服我。

编辑:不管是master开发分支还是其他任何开发分支都没有关系,但问题仍然存在:CI系统是否应还原使构建失败的提交?

另一个(冗长)编辑:好的,我们git以一种奇怪的方式使用。我们认为,分支的概念与真实CI背道而驰,因为提交分支会使您与其他开发人员及其更改隔离开来,并在您不得不重新集成分支并处理可能的冲突时增加了时间。如果每个人都致力于master此冲突,则将冲突减至最少,并且每次提交均通过所有测试。

当然,这迫使您只推稳定(或破坏构建)并更仔细地编程,以免在引入新功能时破坏向后兼容性或进行功能切换。

以此方式进行CI时需要权衡取舍,但这超出了问题的范围(有关问题,请参阅相关问题)。如果您愿意,我可以改写这个问题:一小群开发人员在功能分支中一起工作。如果一个开发人员提交的内容破坏了该分支的构建,则CI系统是否应还原提交?


38
失败的构建应该永远不会master开始。这就是开发和功能分支的用途。这些更改随后进入集成分支之类的地方,您可以在其中测试几个开发人员的所有新功能是否可以一起工作,并且只有在经过测试的情况下才能进入母版。或者至少那是一种可能的工作流程。
thorstenmüller'15

1
@thorstenmüller可以很好地想象所有开发人员都在开发分支中。CI系统是否应还原失败构建的提交?
卡洛斯·坎德罗斯

7
看来您使用git的方式很奇怪。通常,人们应该在自己的分支机构中开发自己的存储库,并且只有在其个人构建的CI确认更改确定后,才将其推送到main。
Wilbert

4
>“将这种冲突减至最少”;合并时冲突较少,但合并不良的问题要多得多。解决方案是作为过程的一部分,不断地从master合并到您的分支,而不是不分支。
deworde

2
...为什么不这样做,以使失败的构建不被开始接受?
user253751

Answers:


55

由于以下原因,我反对这样做:

  • 每当您设置自动工具来代表您更改代码时,都有可能会出错或有可能出现您需要停止更改的情况(例如,最新版的Google Mock)里面有一个错误,所以这不是您的代码失败),并且您不得不浪费时间重新配置它。另外,始终存在因构建系统中的错误而不是代码中的错误而导致构建失败的风险。对我来说,CI就是要让我确信我的代码是正确的。这只会使它成为我担心的另一个潜在问题源。

  • 破坏“构建”的错误类型应该是愚蠢的错误,只需很少的时间即可解决(正如您在评论中所指出的那样,对您而言这是正确的)。如果定期将更细微和复杂的错误放到母版上,那么正确的解决方案不是“更快地修复”,在合并功能分支之前,请多加小心。

  • 在错误得到正确修复的同时,让master无法构建几分钟,不会伤害任何人。CEO不会在任何随机时刻亲自签出master并将代码直接发布给客户(至少,希望不是没有您的参与)。在极不可能的情况下,您需要先发布某些内容才能修复该错误,然后您可以轻松地决定在发布之前手动还原。


1
此外,只有成功的构建才应触发可部署的“构建删除”的创建。如果构建失败,则不应有可部署的构建删除,因此不应存在有人将错误代码发布给客户端的风险。
Mark Freedman

1
肯定还有另一种使用的方法,它比我认为的在大量使用中要好(我们在Twitter上使用)。不要将失败的构建放到master上,愚蠢的错误也很容易修复。请参阅下面的完整答案。
Dean Hiller

26

首先让我们就条款达成一致。

我个人使用术语“持续构建”和“持续集成”来区分两种不同的情况:

  • 连续构建:一种工具,用于定期检查存储库自上次构建以来是否发生了更改,以及是否进行了构建/测试。
  • 持续集成:一种工具,可将拉取请求并使请求可见之前针对最新的头进行验证。

后者称为持续集成,意味着它所保护的存储库始终绿色的1:绝对更好。

您的问题仅对Continuous Build确实有意义,因此我将以您的设置来回答。

1:环境原因也可能破坏构建,例如硬编码年份(2015)的测试可能会在2016年1月开始失败,磁盘可能已满,...当然还有不稳定的困扰。测试。我高傲地忽略了这些问题;否则我们将永远无法到达任何地方。


如果您具有“持续构建”设置,则确实可以自动逆转可能破坏了构建的提交,但是有一些细微之处。

  • 您实际上不能删除提交:其他同事可能已经将它们检出,并在下次尝试提交时将其推回。相反,冲销应该提交冲销差异。哦,同事会讨厌您在正确的时候恢复工作,因为他们必须找到一种方法将其再次推回原处...
  • 实际上,您不仅可以剥离最后的提交(这是一个合并),而且还需要剥离所有提交...直至特定点。例如,最后一次已知的良好提交(在引导系统时要当心)。
  • 您需要考虑外部原因(环境问题),并避免将所有内容都还原为第0天的设置。幸运的是,还原到最后一次已知的良好提交可以避免此问题。
  • 您需要考虑到,最后一次正确的构建可能不再构建(环境问题),在这种情况下,所有进一步的提交都可能被撤消。理想情况下,万一发生故障,并且在还原之前,您将签出最后一个已知的良好构建,然后重新进行测试。如果通过,请还原,否则,发出警报。

请注意,在此系统中,如果测试不稳定或同事经常提交废话,许多好的提交将被撤消。然后您的同事会讨厌您。


希望我的恐怖故事暴露了允许损坏存储库的问题,您现在将实现适当的持续集成管道,其中PR不会直接推送到存储库,而是排队等待合并到工作队列中,并一次集成一个(或汇总):

  • 本地获取存储库头
  • 申请拉取请求
  • 建立并测试
  • 如果成功,则推送到存储库,否则标记为失败
  • 移至下一个请求

两者都尝试过,这绝对是更好的选择。


2
这确实是正确的答案-正确的解决方案是防止不良更改到达master分支,而不是让它们降落然后必须应对它们。
丹尼尔·普里登

我认为这里的问题是发问者认为,“将您与其他开发人员及其变更隔离开”的规定的成本要大于收益。陈述的成本是两个人分歧越长,非平凡合并的危险就越大。海事组织与破损代码隔离的好处显而易见。发问者想采取一种“乐观”的策略,在这种策略中短暂地可以获取破损的代码master,然后在测试失败后解决这种情况。每个人都按照您的建议采取“悲观”策略,并且仅使传递的代码可供提取。
史蒂夫·杰索普

(在这里,“可用拉”的意思是“从...拉出master”,理想情况下,开发人员可以随意地做,但是要实现这一点,必须master在测试和通过之前推迟提交的提交。如果开发人员想要Cherry-pick未经测试或经过测试和失败的代码也很好,并且在这种意义上该代码“可用”,这并不是我要指的内容)
Steve Jessop

正确的解决方案是防止不良更改到达任何分支。失败的提交永远都不应公开。
Miles Rout 2015年

5

这是最佳实践,还是比在开发人员修复母版之前让母版损坏更成问题?

这是有问题的。决定“主HEAD损坏;我将还原最重要的更改”的人与CI系统所做的完全不同。

这里有一些缺点:

  • 自动逆转过程中的错误将使存储库变糟;

  • 这假设一个单一的变更集(最顶层)搞砸了构建(这是不现实的)

  • 维护人员将需要做更多的工作来解决问题,而不仅仅是调查和提交(他们还必须查看反向历史记录)

我们认为,分支的概念与真实CI背道而驰,因为承诺分支会使您与其他开发人员及其更改隔离开来,并在您不得不重新集成分支并处理可能的冲突时增加了时间。

这种信念(分支机构与CI)是不正确的。考虑保留一个稳定的分支,在此仅提交经过单元测试的变更集。其余的(功能分支和本地分支)应由每个开发人员负责,而不以任何方式成为CI策略的一部分。

在功能分支中,您希望与其他开发人员隔离。这使您可以:

  • 执行探索性编码

  • 试验代码库

  • 执行部分提交(有效地提交非工作代码)以设置备份点(以防万一您搞砸了),创建更有意义的更改历史记录(通过提交消息)以及备份工作并完全切换到其他内容(在你写“ git commit && git checkout”的时间

  • 执行耗时较长的低优先级任务(例如,您要执行重构以更改数据层的所有80个类:每天更改两次,直到更改所有这些,然后代码编译(但是您可以执行此操作)而不会影响任何人,直到您可以进行一次提交为止。

如果一个开发人员提交的内容破坏了该分支的构建,则CI系统是否应还原提交?

不应该这样 在CI分支上提交稳定的代码是提交者的责任,而不是自动化系统的责任。


2

我建议使用Gerrit + Jenkins环境,以使主分支始终保持良好状态。人们将他们的新代码推送到Gerrit上,这触发了Jenkins的工作来拉该补丁,进行构建,测试等等。如果其他开发人员喜欢您的补丁程序,并且Jenkins成功完成了工作,那么Gerrit将把这段代码合并到您的master分支中。

@ brian-vandenberg描述的环境类似

除了使分支保持良好状态之外,还添加了代码检查步骤,该步骤可以提高代码质量和有关软件的知识共享。

[1]詹金斯https://jenkins-ci.org/

[2] Gerrit https://www.gerritcodereview.com/


1

CI绝不能更改回购的提交历史记录。

此处的正确解决方案是,如果尚未测试和验证提交,则不将任何提交添加到master分支。

您是否在要素分支上工作,是否让CI自动在那些要素分支上运行,如果构建失败,请不要将其合并到主分支中。

您可以通过在功能分支上运行,以及在构建期间将master / integration / whatever合并到本地分支中,然后运行测试,来构建一个额外的构建,以进行测试合并(如果有问题)。


1
这不会以任何方式回答问题。如果构建在功能分支中失败,则CI是否应还原提交?
卡洛斯·坎德罗斯

如果构建在功能分支上成功但合并之后失败怎么办?
Matthieu M.

@MatthieuM。merge是一个提交,合并的CI步骤是否应还原构建?
卡洛斯·坎德罗斯

@CarlosCampderrós:我个人永远不会有尝试还原提交的设置。太复杂了。
Matthieu M.

我发表了评论。
丹妮丝2015年

1

我们将Jenkins用于构建服务器,并使用网守模型来推送提交-Jenkins和提交触发器(确保同行审阅者已完成工作)的组合是网守。

提交是通过卷发间接推到Jenkins的,在这里Jenkins克隆主仓库,然后拉入要合并的提交并执行所有必需的构建(对于Linux / solaris)。如果所有构建都完成,则提交将被推送。

这样可以避免到目前为止讨论的许多(如果不是全部)问题:

  • 历史改变
  • 如果您是必须修复损坏的开发人员,则可以正确获取历史记录
  • 永远不会引入不稳定(以残破的形式)

它还使我们可以直接执行其他要求,例如成功完成单元测试。


回复:投反对票,您介意对您不满意我的回答发表评论吗?
布赖恩·范登堡

0

您收到多少封自动电子邮件说您的最后一次提交破坏了构建?有多少次错了?但是现在您必须去检查它是否真的是您,或者是大约在同一时间又进行了另一次提交的其他人。也许这是环境问题。

如果系统不确定,那么我当然不想自动化。


0

提出的问题是有缺陷的。我尊重这个说法

“我们认为分支机构的概念与真实CI背道而驰,因为致力于分支机构会使您与其他开发人员及其变更隔离开来。”

这些步骤是您应该做的

  • 如果您愿意,可以关闭主服务器(这很好,并不断从所有人那里获取更改),但不要在本地提交主服务器
  • 在将更改提交给master之前,请使用Submit_XXXXXX创建一个分支
  • 让您的自动构建获取所有的Submit_XXX分支构建
  • 选项1:构建中断或合并中断...更改被拒绝,并且永远不会落在主节点上
  • 选项2:构建作品,詹金斯推送master并对其进行更新

然后,我们要做的是放置一个git commit钩子,以防止每个人实际上都提交给master。它的工作原理很棒。...从来没有损坏的版本,也没有来自主服务器的还原提交。

后来院长

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.