如果两次提交之间的等待时间过长,该怎么办?


100

我很调皮……太多的“牛仔编码”,还不够提交。现在,我在这里做出了巨大的贡献。是的,我应该一直坚持下去,但是现在为时已晚。

什么是更好的?

  1. 做一个非常大的提交,列出我所做的所有更改
  2. 尝试将其分解为可能无法编译的较小提交,因为文件具有多种修复,更改,其他方法名称等。
  3. 尝试仅针对适当的提交对文件进行部分还原,然后放回新的更改。

注意:到目前为止,我是唯一从事此项目的程序员。至少在我们雇用更多程序员之前,唯一会查看所有提交评论的人就是我。

顺便说一句:我正在使用SVN和Subclipse。在进行任何这些更改之前,我确实创建了一个新分支。

更多信息:我首先问了一个与我如何进入这种情况有关的单独问题:如何为重写应用程序的粘合做准备


2
您正在使用什么版本控制程序?许多模块都具有允许您按“大块”分割编辑的模块,即,多行修改的行,这将使您可以按自己喜欢的方式对编辑进行分组,并将一个文件的mod分发到多个变更集。例如,Mercurial具有“货架”扩展名。当然,如果这对您的过程很重要,您仍然应该检查是否可以编译每一批更改。麻烦是否全都取决于您和您的商店。
亚历克西斯

6
至少在分支上签入,这样您就不会丢失更改。
罗里·亨特

2
您可以继续问自己这个问题并等待更长的时间,或者实际上犯下并处理造成的任何混乱……然后……不要再做!
haylem 2014年

40
#1,祈求宽恕,然后不再犯罪:)
Peteris 2014年

5
您应该问自己一个更重要的问题:“我该如何改变我的不良习惯,以防止这种情况再次发生”。应该没有理由每天至少做一次,多做一次更好。
布朗

Answers:


52

要回答这个问题,您必须问自己,将来如何使用这些提交的结果。最常见的原因是:

  • 看看引入了什么版本的错误。
  • 了解为什么存在某些代码行。
  • 合并到另一个分支。
  • 为了能够检出先前版本以对客户或测试人员在该版本中看到的问题进行故障排除。
  • 能够包含或排除发行版中的某些部分。

假设您可以创建一个签入消息,该消息同样适用于每行更改的代码,则前两个原因也可以通过一次大签入得到解决。如果您是唯一的程序员,则较小的提交不会使您的合并更容易。如果您不打算仅对部分未提交的更改进行发布或测试,则后两个原因不适用。

进行小额提交还有其他原因,但这是因为您正处于更改中间,而时间已经过去。这些原因使得更容易排除错误或实验性更改,并且更容易与同事保持同步,而无需进行大量可怕的合并。

从我对您所描述的情况的理解来看,在这一点上拆分承诺似乎没有什么好处。


很好的答案!尽管我对不做小事情并没有感到遗憾,但我对如何尽可能有效地恢复良好行为应该做的事情感到更好。
durron597 2014年

1
关于3和5的另一件事是,为了使它们发生,您现在要做的任何工作都可以等到实际需要时再进行相同的工作。将来可能会有些困难,因为您对所做工作的记忆已荡然无存。但是话又说回来,您可能永远都不需要它了。
史蒂夫·杰索普

以我的经验,依靠版本控制注释来讲故事为什么存在代码是麻烦且脆弱的(即原因1和2)。如果您将SVN与分支一起使用,则无论如何,提交历史都会在合并时丢失(使用git等更现代的东西会更好)。因此,恕我直言最好将其与评论一起使用。
汉斯·彼得·斯特尔2014年

1
@hstoerr-如果您使用的是Subversion 1.5或更高版本,则可以在合并时使用--reintegrate选项保留历史记录。
达斯汀·肯德尔2014年

1
git add -p是您最好的朋友。我爱上了这个功能。这样,我可以将我的编码标准修改提交到单独的提交中,并使相关的代码更改保持隔离。
Spidey 2014年

39

我认为无论您做什么,都尽量避免签入您知道不会编译的代码。

如果您认为您的第三个选择是可行的,那么只要您可以确保提交顺序不会创建无法编译的系统,那可能是一个不错的选择。否则,只做一个大的承诺。这很丑陋,但是很简单,快速,并且可以完成。往前走,多做点事情


选项三是可能的,但将非常耗时。我想我将要做选择1
durron597 2014年

3
提交无法编译或构建在功能分支(或类似分支)中的代码有何弊端,这些代码如此可怕,以至于迫使某人避免这样做(无论他们做什么)?我猜想其他人可以避免任何真正可怕的提交,这是我首先要避免使用它们的唯一真实原因(当然,假设这些提交没有被释放)。
肯尼·埃维特

3
“避免代码,将不能编译检查”只适用于共享代码库/分支。在单人项目或单人开发分支中,我声称将更改纳入VC更重要,这样您就不会失去任何东西。
Stephen C

3
例如@StephenC,因为它破坏了git-bisect之类的工具。如果代码一直在编译/运行,并且您需要找到一个回归(如果它一直在编译),则只能进行二进制搜索(更不用说如果代码块中存在回归,则您需要进行较大的更改而不是缩小范围)它下来)。
Maciej Piechotka 2014年

@MaciejPiechotka-好吧,很明显,如果您需要在私有分支上使用特定的工具,并且它们要求代码可编译,则可以这样做。但这对于一个人的项目/分支来说并不常见。
2014年

19

进行频繁,小而有意义的提交的最重要原因是帮助理解代码的历史。特别是,如果很难生成可理解的差异,则很难理解代码的变化方式。

选项1混淆了您所做的更改的历史记录,但否则不会造成任何问题。

选项2掩盖了您所做更改的历史,可能比选项1少了一些,但是如果他们假设或以其他方式认为提交是不同的,例如可能可以独立合并到其他分支中,则可能给您自己或其他人造成其他问题。除非有很强的实际原因,为什么它比选项1更受青睐,所以它并不理想。

选项3是最好的,其他条件都相同,但是,如您在其他地方所述,如果这样做需要“极长时间”的时间或会导致其他重大成本,则您必须权衡这些成本与预期的收益。创建更清洁的提交。

根据您提供的信息,我选择选项1。也许您应该设置提醒以提示您进行更改?

原型设计和重写

需要记住的另一个考虑因素,尤其是考虑到您是唯一的程序员,以及我怀疑您正在开发一个相对较新的代码库时,养成在习惯于在您更改代码时养成不同习惯的习惯可能是个好习惯正在对新代码进行原型设计,而不是维护或扩展现有代码。两者之间可能没有十分清晰的区分,但我认为这仍然是一个有用的区别。

在制作新代码的原型时,几乎可以肯定在分支中,但也可以在单独的项目中,只要要保存更改就提交。或者甚至完全可以在版本控制之外工作。相反,您可以专注于收集有关您正在考虑的各种假设或设计的可行性的证据。我经常使用其他工具(例如LINQPad而不是Visual Studio for C#代码)编写小型原型。

验证特定的假设或设计后,请在您的主项目中(最好是在分支中)重写它,并进行有意义的小型提交,以最好地帮助他人(包括将来的您)了解更改的性质你在做。


1
好答案; 肯尼(Kenny)您是否有一篇不错的文章或其他知识库,可以与有关原型的更具体细节链接?我的原型制作版本是“在笔记本或白板上绘制草图”
durron597 2014年

@ durron597,我想不出我头顶上的任何链接(甚至是寻找链接)。我已经尝试了足够多的解释(和动态编译)编程语言,甚至没有想到“原型”的想法可能是新颖的!而且,我已经重写了很多C,C ++和Java程序(一次又一次),以至于我认为这可能也不罕见,或者至少对于某些人来说是新颖的。
肯尼·埃维特

12

尽管唯一合理的答案是永不折断行李箱,但有时是不可能的。例如,如果您提交过多,svn可能会中断提交(我不确定是选项还是功能)。在这种特殊情况下,只需分段检查即可。由于您是一个程序员,因此不会打扰任何人。

因此,我会选择选项1。如果不可能,则选择选项2。

选项3需要付出很多努力,但这根本不值得。


1
或将未编译的版本标记为“不编译”
棘手怪胎2014年

2
@ratchetfreak:我猜想SVN中的“标签”没有多大帮助,因为标签在树干上不能作为“注释”。
布朗

@DocBrown我的意思是将其添加到提交消息中
棘手怪胎

5
@ratchetfreak我会做“份X / N:在ABC检查-犯规编译”
BЈовић

选项3不需要太多的工作。另一个答案说明了如何使用git add --patch和轻松快速地做到这一点git stash。由于源控制工具和知识已经过时,这种情况似乎很难解决。
罗恩·麦克尼尔

7

尝试将其分解为可能无法编译的较小提交,因为文件具有多种修复,更改,其他方法名称等。

当我发现自己处于类似情况时,我使用了以下技术:

  1. 仅添加与特定功能相关的代码: git add --patch
  2. 隐藏所有其他更改: git stash save --keep-index
  3. 运行测试/尝试编译
  4. 如果一切正常,请提交更改,否则请转到1

我对SVN不熟悉,所以我不知道这是否适用于您的特定情况,但是基础应该是相同的-隔离一小部分代码并分别进行测试。


我喜欢这个,但不幸的是,我的待办事项清单上有很多事情(当您是公司中唯一的技术人员时有很多事情)是从SVN切换到git,而我只是还没有适应它。
durron597

1
由于我不够使用--patch,我在各种编辑器窗格中使用“撤消”来进入较早的工作状态并提交它们。然后我重做下一次提交。由于处于撤消状态时倾向于对代码进行少量添加,因此我总是在开始此过程之前进行备份
joeytwiddle

使用git,您还可以在提交之前进行交互添加(add -i),然后进行分支以独立验证提交。
riezebosch 2014年

3

选项4怎么样:在临时位置备份仓库的当前状态,将仓库恢复为原始状态,列出所做的所有更改(您仍然可以查看临时备份),然后手动重新实现(并编译)和测试!)作为单独的提交。

这应该更容易一些,因为您已经编写了代码,只是从临时备份中找出要复制和粘贴的部分。

当您干净地重新实施每个更改并因此确保提交是独立的,小型的且可编译的时,您可以删除临时备份,并且几乎所有内容(提交的时间/日期除外)都与之完全相同。如果您从一开始就正确地做,那将会是。


这只是做选择#3的一种方式。可能是最好的方法,但确实很费时间。
durron597

当我进行一次大提交时,有149行添加/删除/发送消息。至少要花半天的时间。
durron597 2014年

@ durron597我不同意,我认为这与#3不同。关于149行,您如何看待干净的提交历史记录?花半天值得吗?无论如何,这并不像其他方法不需要确定哪一行应该在哪个提交中一样,因此您将不得不以任何一种方式遍历149行。时间的差异将很小。
极好

嘿。我有足够的经验知道要使用版本控制,但是没有足够的经验来保存版本控制:)因此,做事的实际原因还是有点学术性,如果您知道我的意思的话。
durron597 2014年

您不必备份整个存储库。您可以进行“备份”提交,然后使用来回滚HEAD git reset HEAD~git reflog如果您以后决定需要,您的提交仍会存在。您甚至可以在进行重置之前先分支一个分支(然后切换回工作分支),然后为您的“ backup”提交名称。如果不需要,请稍后删除该分支。编辑:抱歉没有意识到OP在svn上!
joeytwiddle

3

您是唯一的程序员。只需进行一次大规模检入,详细说明您所做的工作。

您是否可能回滚所做的“部分”操作?如果不是,则绝对继续执行选项1。

将代码检入版本控制系统有两个原因。当您是唯一的开发人员时,所有这些都围绕安全性展开-即,如果您搞砸了,机器死了或其他原因,您总是可以回到最后一个检查点。

稍后进入项目的程序员不太可能想要回滚到未编译的版本。因此,恕我直言,选项2是疯子。

选项3听起来像是在浪费时间,如果我是您的老板,并且看到您在浪费时间进行此操作,那么我将与您讨论一下您的时间是值得的。

要进行迭代:通过检入代码,可以在机器出现故障的情况下覆盖/节省您的屁股。在一个人的团队中,其他所有东西都是橱窗装饰。


1
回滚不是使用小型提交的唯一原因。这甚至不是一个特别好的理由。主要原因是能够查看何时以及为何进行更改,并在遇到未知来源的问题时方便进行故障排除。进入项目后期几乎可以肯定的另一个程序员至少偶尔会遇到的代码行,让他走“跆拳道”,并指回提交它被第一次写或最后修改。如果那个承诺是改变500件事的巨大承诺,那么就不可能从历史中获得任何有用的信息。
亚罗诺(Aaronaught)2014年

顺便说一句,这就是为什么使用Git的团队通常讨厌合并提交,而讨厌请求/要求重新设置基础。合并提交中断bisect和通常用于隔离问题的其他技术,因为这么多更改被塞进一个巨大的提交中。
Aaronaught

1
从个人的角度来看,我同意除非您要彻底更改代码库,否则您不应该进行大型提交。但是,我们所谈论的是一个程序员,该程序员基本上已经处于断开连接状态,并且现在正试图重新做正确的事情。在那种情况下,我认为一次提交是可取的。
NotMe 2014年

1
@Aaronaught我要补充说,三个月后,您自己可以构成“另一个程序员”。
Maciej Piechotka 2014年

1
我也不得不不同意分支作为架构更改或其他“破坏性”更改的可行策略。这只会导致合并冲突和合并后错误的噩梦。从长远来看,找到一种将主要变更分解为较小的,向后兼容的变更的方法,或者在最坏的情况下,使用Fowler,Humble和其他人称为Branch的方法,要痛苦得多。通过抽象(实际上根本不是分支)。这两种策略都意味着较小且集中的承诺。
Aaronaught

2

我的规则是:未经认真的代码审查就不能签到。如果我对我自己的,我得检讨自己的代码,但它进行审查。您似乎已经进行了许多其他人无法审查的代码更改,因此您无法自己进行审查(审查自己的代码更加困难,需要更多的纪律,因为您会自动做出错误的假设,认为自己的代码正确无误)。

每个人的牢不可破的规则是:切勿检入甚至无法构建的代码,并认真避免检入无效的代码。

解决方案:复制更改的代码,回到原始点。一次将一个更改合并到原始代码中,对其进行检查,测试并将其检入。使用您描述的编程方法,您一定会发现这种方式的严重错误。

这也是训练自己良好的编程习惯的好方法。


从逻辑上讲,这与上述(git add --patchgit stash)基于Git的答案相同,并且是现代DVCS可以轻松处理而旧系统无法解决的一个很好的例子。
罗恩·麦克尼尔

1

我想你太担心了。如果您是唯一的程序员,并且没有适用的规格表,那么您的工作完全取决于您。我认为没有人会因为做出较大的提交而惩罚您,因此您将遇到的唯一问题是技术问题,例如无法回滚提交中的单个文件更改。由于此时您仅由仓库控制,这也不是一个大问题。

实用主义和教条主义之间要划清界限。在团队中,您所做的并不是一个好主意,并且可能不应该重复进行,但是在您的情况下,我将提交大型提交。


1
这似乎并没有对先前的12个答案中已经发布的内容增加任何实质内容
gnat 2014年

-1

问题不在于提交之间的长时间延迟,而在于您将代码保持在不可编译状态的时间过长。首先,您对“长期”的定义是什么?对于某些人来说,过渡状态5分钟太多了,但有些人甚至可以在几天之内完善其代码,而无需尝试运行编译器。

实际上,这并不重要-重要的是您失去了对代码的控制,您的代码变得不可管理。这是正常现象,这只意味着您有技术债务,现在该考虑重构了。所以你感到沮丧吗?您的代码无法编译,甚至没有单元测试?在这种情况下,您如何考虑重构?别担心。完成您的“牛仔编码”,然后开始清理它。理想情况下,尝试编写一些测试。你没有时间吗?好的,从小的改进开始。

某些更改不需要测试。更改变量名称以使其更适合,将重复的代码移到单独的函数中,依此类推...您将更好地了解代码。之后,您可以进行更大的更改。同样,如果可能,尝试编写测试。使代码易于管理。

之后,您将看到下一个更改不会花费您太多时间(无论它意味着什么)。


2
他没有说过很长一段时间以来一直无法编译代码。回购中的代码很长一段时间都未修改-虽然很旧,但是仍然可以编译。他的工作副本中的代码经常更新,但未提交。问题中没有任何内容表明他的代码可能需要重构-“牛仔编码”在这里是指他的SCM工作流程,而不是指实际的代码质量
Idan Arye 2014年

@IdanArye来自原始问题...Try to break it into smaller commits that likely won't compile...如果某件事妨碍您提交代码,而这已经是一个好主意,则很难管理该代码。“提交”只是坚持工作的一种方式。我们可以考虑更极端的情况-“如果某件事阻止了我保存源文件”。那会是什么呢?我猜这是担心自己的变化。为什么会这样呢?...我想你明白了
AlexT 2014年

2
在我看来,阻止他犯罪的原因似乎仅仅是懒惰。
Idan Arye 2014年

@IdanArye你在所有方面都是正确的。加上没有做足够的TDD,这是一个单独的问题。
durron597 2014年

@AlexT考虑一种情况,其中您修复了两个错误,其中一个需要新开发的方法。如果您已正确提交,请先修复一个错误,然后再提交另一个错误。如果不是,那么在提交时,您必须将两个更改都包含在同一提交中,或者将第一个错误修复与第二个更改一起提交,除非提交的版本没有新方法调用,因此不编译。
durron597 2014年
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.