每天提交/签入代码是一种好习惯吗?


63

我一直在阅读Martin Fowler关于持续集成的说明,他将其列为“每个人每天都致力于主线”。

我不喜欢提交代码,除非正在处理的部分完成并且在实践中我每三天提交一次代码:一天用于调查/重现任务并进行一些初步更改,第二天完成更改,以及第三天编写测试并清理^以提交。我不愿意早日提交代码。

现在,我通常每天两次从存储库中提取更改并将其集成到本地,但是除非我能完成较小的工作,否则我不会经常提交更改。

问题:每天做这样一个好习惯,是否应该更改工作流程以适应它,还是不建议这样做?

编辑:我想我应该澄清一下,我在CVS中的意思是“提交”(也称为“推送”),因为这可能是Fowler在2006年撰写此书时的意思。

^顺序更加随意,并取决于任务,我的意思是说明时间跨度和活动,而不是确切的顺序。


20
如果代码可以编译并执行一些有用的逻辑,则可以提交代码。如果您在团队环境中工作,最好在短周期内提交代码。
EL Yusubov

4
Martin Fowler是否假设未分发的VCS?
user16764

4
请注意该文章的日期:2006年5月1日。Git和Mercurial 直到2005年4月才开始使用,我的印象是,它们实际上在2008年左右开始受到关注。我在Fowler的网站上找不到任何引用的文章到2009年之前的任何一个都可以。该建议不适用于使用DVCS的团队。
Kyralessa

2
@Kyralessa:该文章甚至指出“ Subversion是现代的[版本控制系统]”。

4
首先是代码,然后是测试?

Answers:


43

我不同意这条规则,也同意梅森·惠勒的观点。我想补充一些想法。

每当我有一个有意义的更改要提交时,我都会尝试提交:如果我修复了几个小错误,这可能一天两次,如果我正在开发一个较大的软件,而其余部分无法使用,则每周一次。代码以任何有意义的方式,直到达到一致状态为止。

另外,我将提交解释为发布有意义的修订,该修订为代码库提供了新功能。我认为应该在提交之前尝试清理代码,以便其他开发人员在查看修订历史记录时可以理解更改的含义和目的。其他开发人员在历史记录中看到的更改越少越好:当我查看修订历史记录时,我希望看到增加一些有意义的功能的增量;我对每个开发人员的每个小想法都不感兴趣,并想在他们解决方案之前尝试一下。

此外,我认为使用SVN服务器(或任何版本控制系统)作为提交当前代码快照(前提是可以编译)的备份工具不是一个好主意:您可以使用USB记忆棒或外部USB驱动器或网络磁盘来镜像您当前的代码,这样即使您的计算机出现故障也不会丢失它。版本控制和数据备份是两件事。发布修订保存 代码快照不同。

最后,我认为时不时地提交(即仅当人们真正对代码的当前状态感到满意时)应该不是问题,并且避免合并冲突并不是经常(过多)提交的合理理由。许多合并时,不同的人对同一文件的工作在同一时间,这是一个不好的做法(见例如冲突发生这篇文章中,7点)。应该通过将项目分成具有清晰接口和尽可能少的依赖关系的模块,并协调开发人员的工作,以使他们工作的代码尽可能少地重叠,来减少合并冲突。

只是我的2美分。

编辑

我想到反对过早提交的另一个原因是(非常多的)错误版本无法测试。如果您要进行测试,并且测试团队每天都在测试,则他们可能在几个小时(或一天)内没有可测试的版本。即使您不尝试修复该错误,而只是还原您的更改,重建也可能需要几个小时。假设有五名测试人员在您的团队中工作,由于不活动,您浪费了5 x 2 = 10个小时的团队时间。它发生在我一次,所以我真的尽量避免名称过早提交尽快提交


23
“提交”不是“发布”。“提交”是指“快照”;在scm-lingo中,“发布”被称为“推送”。当然,SVN只是将两个概念合并为一个,从而使许多合理的工作流程变得不可能,但这只是工具的局限性,而不是一般的源代码控制工作流程。
tdammers

3
Revision control and data backup are two different things是的,我绝对是这样。
雪橇2012年

1
@tdammers:我的意思是以非正式的方式发布:只要代码在我的计算机上,这就是我对通用代码的私人更改。一旦我提交了它,它就会被发布,这是团队其他成员所知道的,也是正式项目历史的一部分。
乔治

1
在这种情况下,“提交”可能是错误的词。许多SCM允许本地提交,与团队其他成员共享您的代码是一项单独的操作,通常称为“推送”。再次,SVN将这两个概念结合在一起,但这是该工具的局限性,如果它妨碍了您的工作流程,请考虑切换到其他SCM。
tdammers

@tdammers:要明确区分本地提交和发布将是向前迈出的一步。在SVN中,我可以为此使用单独的分支。但是,我再次想知道为什么我要跟踪对我来说意义不大的修订?我不能说我要一个新的修订本(甚至是私人修订本),只是因为它是5点钟,我要回家了。我更喜欢备份。
乔治

107

一天几次提交代码。每当我到达足以完成代码编译且不会破坏其他功能的地步时,它就会进入。

您应该考虑分手工作,以便每天可以安全地办理几次登机手续。

这样做的理由有两个:

  1. 任何未检入的工作都可能会丢失-您的计算机可能会发生灾难性的故障。在这种情况下,等待时间越长,您损失的工作就越多。
  2. 您不签入而做的工作越多,当您最终决定烘烤时,其他人将需要集成更多的代码。这会带来更多冲突和合并问题的机会。

2
如果您在冲突和合并问题上遇到了严重的问题,则意味着您的项目经理没有做好工作。涉及相似功能的多个案例应该交给同一位开发人员,正是这样,您才不会有两个或两个以上的编码人员来踩踏彼此的工作。
梅森惠勒2012年

14
@MasonWheeler-经过3天未完成的工作,很可能一个人触摸了别人同时拥有的代码。如果您有很多程序员这样做,那么最好的项目经理将无法避免发生冲突。
奥德

3
@Oded:也许吧。我想我的回答被我在一个足够大的代码库上的经验所打动,以至于我们的开发人员(团队中大约有十二个编码人员)都倾向于承担不重叠的职责。不确定较小的项目会有什么不同。
梅森·惠勒

3
@ArtB-如果有像您这样的人每三天检查一次怎么办?还是每周一次?您要依靠别人做正确的事。
奥德

3
当我读到问题时,我的回答是“就像问每周洗澡是否一个好主意”?
安德鲁·格林

39

盲目地坚持任何方法论或实践而不理解其背后的原因从来都不是一个好主意。这就是崇尚货色编程的地方。

因此,“我应该每天做出承诺,因为马丁·福勒这么说”只是愚蠢的。有时这也是不切实际的。如果您正在使用复杂的新功能,则可能需要几天的时间才能找到值得检查的地方。

这并不意味着您应在签入之前确保所有内容均完好无损。这是在出现问题时丢失工作的好方法。正确的做法是在此问题上发展并运用良好的判断力。经验法则只能帮到您很多。


1
然后,如果是复杂的功能集成/开发,那么不将其提交(也许不提交给主干)仍然是一个很大的损失,但是至少在该功能的分支中,这就是分支的目的!
文森特·B。

2
您是什么意思“值得入住”?如果它没有破坏任何人的代码,为什么不检查它呢?
Kirk Broadhurst,2012年

2
“您的意思是'值得签入'?如果它没有破坏任何人的代码,您为什么不签入呢?”:因为我不想保留代码的旧副本,因为它们存在于某些地方时间点。如果代码中包含一些将来可能需要检索的有用信息,我也希望保留该代码的旧副本。否则,我只会在修订历史记录中产生无用的噪音。
乔治

3
+1。我曾经在一个团队中工作过,即使代码是高峰或无用的调查,我们每天都必须将代码检入到vcs中。它被证明是低效且浪费的,特别是因为它需要定期维护以清理vcs。这是由于妄想症的组合,因为他们可能冒失去一点时间来重做某事的风险,并且因为经理已经读了一本书,所以您每天都要犯错。也许是一个极端的例子,但是很严重的是,如果您没有判断是否值得检查某些东西的判断,那么您可能不太适合这份工作。
S.Robins

14

Oded提出了两个重要原因,要求它们尽可能频繁地提交代码。我还要添加一些:

  1. 在编写代码时,其他人可能需要对该代码进行一些处理。他们不应该等待6天才能得到它。在这种情况下,我的同事通常在我的代码段中创建一个原型,提交,然后添加主体,然后再次提交。通常这需要几个小时。

  2. “通用”代码使每个人都能尽快看到所有更改。如果您正在处理的代码段与其他人的工作完全分开,并且您不希望它们等待,那么建议创建一个分支供您处理,然后,如果一切成功,则将其合并到主线。


1
为什么(IMO)的答案是唯一如此正确且正确的答案(第2点)?当然,这就是分支的重点!@Mason Wheeler:因此,您喜欢原始编码几天而无需一次提交?那为什么要使用版本控制系统呢?
文森特·B。

2
这是正确的答案。如果您的任务需要大量工作才能使用,则分支。否则,您会在工作正常进行时进行提交以确保团队成员具有最新版本,他们可以测试该版本是否工作,并尽快识别添加/缺失的功能。
Kirk Broadhurst

“因此,您喜欢在原始数据中编码几天而无需一次提交?那为什么要使用版本控制系统?!”:因为最终您确实想提交修订,即使您不必每天都盲目地提交。而是由您决定是一天几次提交还是连续三天不提交而工作。我确实看不到提交一些没人能使用的未完成功能的意义:只需进行备份,第二天就可以完成并提交。
乔治

8

我坚信进行所有值得保留的合理更改。经常提交,如果代码不值得保留,请将其恢复为干净状态。您等待回推/发布代码的时间越长,实现起来就越困难,并且遇到的问题也就越多。您还将更快地获得有关您的贡献的反馈:

  • 他们会破坏建筑吗?
  • 您是否正在复制其他团队成员的工作?
  • 你做错什么了吗?
  • 还是人们在等你的事情?

较小的更改更易于管理。

另外,值得注意的是不同版本控制系统之间的差异。有些工具(例如Git(分布式))将允许您在本地提交和控制整个历史记录,只有在准备好发布时才进行推送。其他诸如SVN(集中式)之类的方法将结合这两个步骤,使小的提交非常低效。

不要忘记,您的提交本质上是变更文档。如果出现问题,您将很高兴拥有更多的历史记录。对我来说,一次提交一个星期的工作似乎毫无用处。我最终将阅读更改的每一行代码,而不是读取每个逻辑块的摘要。


5

我认为这里的大多数答案都错过了马丁·福尔斯(Martin Fowlers)声明的要点之一。这与持续集成有关未检入(推送/发布/合并)到主线中的代码未经过测试。

这不应被视为鼓励您在每次离开办公室时提交本地计算机中所拥有的任何代码。正如其他一些人指出的那样,这很糟糕,会破坏构建并导致不稳定的主线。

但是,鼓励您尝试以较小的步骤进行更改,这些更改可以签入主线而不会引起问题。这鼓励了代码的进化,而不是将其全部撕裂并重写。

现在,这种工作方式有什么好处?

  1. 不提交大量代码或进行革命性更改会减少破坏构建的机会。
  2. 如果您的提交破坏了构建,那么确定问题所在,还原并随后快速提交固定版本非常简单。
  3. 通过确保所有测试都在代码的每个小变化上运行,可以确保您不会引入细微的错误或回归,而这些错误或回归可能是由于代码超出了持续集成方案而产生的。

当然,并非所有的变化都适合这种方法。正如其他人指出的那样,没有规则是绝对的。但是,对于预期在很长一段时间内不会出现在主线之外的更改,请使用其自己的持续集成方案设置备用主线,并采用相同的方法来实现。使用当今的分布式VCS,这是一件相当容易的事情。


+1:“当然,并非所有更改都适合这种方法。” 我认为这是重点。我觉得福勒的建议还可以,但应该根据具体情况进行判断。取而代之的是,该建议通常被推广到一个绝对规则,并且无需进一步考虑即可遵循。
乔治

@乔治,我对此完全同意。无论是谁支持,都不应将任何建议作为绝对规则。
哈拉尔德

关于此的更多想法。“未对未检入(推送/发布/合并)到主线中的代码进行测试。”:我同意这是一个很好的原则,不应等待数周才能检入并对其代码进行测试。但是,盲目地应用此原理会导致甚至无法测试的损坏应用程序(我已经看到了现场直播:整个测试团队闲置了几天,无法测试任何代码,直到代码恢复可用状态)。也许其他用户写的内容适用于某些情况,但通常不适用。
乔治

1
签入不稳定的代码永远都不行。破坏CI的提交应被还原。如果您经常进行较小的增量更改,则与发生长时间未经测试的大型更改相比,引入此类破坏的机会较小。如果它破坏了构建,还原也可能会更容易。但是,正如您所说,有时候,除了颠覆性变革之外,别无他法。然后,请尽最大可能对其进行抛光,并提交进行全面测试。重点不是遵循规则,而是了解建议的来源。
哈拉尔德

3

每天检查的参数:

  • 存储代码并备份以防硬盘故障
  • 活动可以记录在提交记录中(我在星期四做了什么...?
  • 与现有代码库的集成发生得较早,并且块较小,希望可以早日发现冲突或合并问题
  • 您的团队可以看到您所做的工作
  • 您的同事可以更快地针对您的界面进行工作,从而使他们有更多时间与您的“大型复杂代码”集成
  • 您的代码将更快地经过实际测试,或者至少要经受比实际使用更多的使用,从而可以更早地确定错误或遗漏。

反对每天检查的论点:

  • 不需要或不想
  • 还没有“清理”我的代码,很乱
  • 没有时间

我认为除了懒惰或混乱之外,没有足够的理由每天检查一次。没有什么比看到在开发环境中运行的代码与开发分支中的代码不匹配更糟糕的了,因为有人“还没有完成”,因此还没有签到。

我想错了,所以请让我知道反对每日入住的任何正当理由。


“我认为除了懒惰或混乱之外,没有足够的理由每天检查一次。”:我相信相反的原因完全相同。我可以花些时间查看代码的当前状态,并确定它是否包含一些值得记住的相关信息,或者,如果我懒惰而混乱,我可以简单地将其检入(并生成少量信息的额外修订版)内容),只要它可以编译。
乔治

1
我理解您的观点,即不应懒惰并每天清理其代码以便可以将其检入。另一方面,在处理某些复杂的代码时,这很难实现,因为清理可能要花费几个小时,您每天都不能花费几个小时来清理代码。
Giorgio

@Giorgio因此,您花了几天的时间清理代码?我已经给出了每天检查的一些很好的理由-您的理由是您将必须清理代码?只需直接编写更干净的代码。
柯克·布罗德赫斯特

这并非总是可能的,例如,如果我从头开始开发一些复杂的代码(> 4000 LOC),则需要进行大量的实验才能正确。在一天结束时,代码很可能会有些混乱,并且直到两天后我进入一个一致的状态,我才想修复它。不幸的是,我并不聪明,无法想到完成的,完美的代码形式,而且我总是可以在几个小时内(即一天结束)将它们全部写下来。我最近有这样的经验,典型的开发周期(从一个一致的状态到下一个一致的状态)是2、3天。
Giorgio

@Giorgio您没有要检查的开发分支吗?应该检入代码,以便其他人也可以查看和测试它。
柯克·布罗德赫斯特

2

如果您将“提交”的意思是“合并到主线”,那么您绝对不应该每天都在要发布给客户的软件项目中这样做。您应该合并已完成并经过测试的更改,以使主线始终有效且可发布,并且不会因某些功能未完成而处于损坏状态。

但是,使用当今的分布式版本控制的奢侈之处在于,您既可以保持主线稳定,又可以在git/hg/whatever commit每次感觉要保留事物状态的同时进行操作。我每隔几个小时(绝对是每天结束)这样做一次。

使用DVCS,您可以发布您的工作,与团队中的其他人进行协作,并使其与主线分支中的更改保持最新。您可以在不影响客户和/或其他团队所依赖的代码稳定性的情况下完成所有这些工作。

在Subversion是最新技术并且无法无痛苦地分叉和合并要素分支的时代,拥有同时构建多个不同要素的主线可能是最好的方法。但是,这种优势并没有超过2010年。


2

在Team Foundation Server中,您可以“搁置”,这与签入不同,而只是对代码进行备份,以便在计算机死机时也不会丢失所做的更改。

我也看到过具有“开发人员线”和“主线”的软件公司。开发人员只要认为合适就可以自由签入开发人员线,并且只有团队负责人才能访问主线,因此开发人员可以在生产就绪时将代码从开发人员复制到主人员。

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.