什么git提交练习更好?

时间:2013-03-21 16:37:36

标签: git merge commit rebase bisect

我真的相信在一个问题上有一个提交是一个好习惯。我确定我在“最佳实践”这样的文章中的某处读过它。

因此,我的工作流程如下:

  • 对于新问题,我使用git checkout -b new-issue创建了一个新的本地分支。
  • 将所有更改提交到其中。有时这涉及提交批次
  • 完成后,我squash提交,rebase他们进入当前主题分支。
  • 如果出现问题,我可以git revert提交,找到错误,修复错误,并将新补丁提交到专题分支。我不会更改远程存储库的历史记录。

但是今天,我听到以下工作流程后感到很惊讶:

  • 为新问题创建新分支。
  • 承诺一切。
  • 使用merge --no-ff将问题分支与专题分支合并(因此我们将{merge}提交“revert。”
  • 如果出现问题,我们可以使用git bisect来查找错误。

根据第一种方法,我们将有一个干净的git历史记录,并且不知道在开发过程中使用的开销分支。

根据第二种方法,我们将有一个非常混乱的历史,有很多丑陋,不必要的合并和提交只有一个问题。但是,我们可以使用git bisect来查找错误。 (也许这对于重构更好?)


  • 您对这两种方法有什么利弊?

  • 您使用哪种方法?为什么?

  • 在实践中,您是否真的使用git bisect来查找错误? (我没有...)

2 个答案:

答案 0 :(得分:7)

第二种方法不必有很多丑陋和不必要的合并和提交。这是我喜欢做的事情:

  1. 创建新主题分支
  2. 制作一堆提交
  3. 在合并回父分支之前,清理提交:
    • 重新定义到最新版本的父分支
    • squash typo fix commits
    • 拆分提交一次做多个事情进入单独的提交
    • 对提交进行重新排序,以便审阅者更容易理解更改顺序
  4. --no-ff合并到父分会
  5. 以上步骤会产生如下历史记录:

    *   354b644 Merge branch 'topic3'
    |\
    | * 54527e0 remove foo now that it is no longer used
    | * 1ef3dad stop linking against foo
    | * 7dfc7e5 wrap lines longer than 80 characters, no other changes
    | * b45fbcf delete end-of-line whitespace, fix indendataion
    |/
    *   db13612 Merge branch 'topic2'
    |\
    | * 961eebf unbreak build by adding a missing semicolon
    |/
    *   a5b6b16 Merge branch 'topic1'
    |\
    ... (more history not shown)
    

    上图与方法#1具有相同的优点:

    • 您可以使用--first-parent参数git log获得一个简洁的摘要,类似于您使用方法#1获得的内容:

      * 354b644 Merge branch 'topic3'
      * db13612 Merge branch 'topic2'
      * a5b6b16 Merge branch 'topic1'
      ... (more history not shown)
      
    • 您仍然可以轻松检查主题分支中所做的全部更改。例如,git diff 354b644^..354b644将显示主题#3的更改内容。

    但是你得到的好处是方法#1无法给你:

    • 历史记录 更容易查看:提交b45fbcf7dfc7e5(针对topic3分支)引入了大量噪音,但没有实际的逻辑更改。有人试图回答这个问题,“对主题#3做了哪些逻辑修改?”如果把所有这些提交都压成一个,那么可能很难深入挖掘噪音。
    • 合并提交很好地识别合并分支上的一系列提交的上下文(例如,这组提交是为了解决主题#3)。
    • 更精细的提交粒度可以更容易地弄清楚为什么会进行特定的更改,这可以帮助区分意外更改和有意 - 但微妙。
    • 如果有多人在分支机构进行合作,您可以看到他们都是谁以及每个人贡献了多少。
    • 合并主题分支的提交次数可让您大致了解已更改的内容。
    • 提交的时间范围可以提供有用的上下文。
    • 您可以轻松地挑选在不同分支上进行的特定更改(例如,选择将错误修复到发布分支所需的最小更改)。

    我可以想到一个缺点:可能很难将软件开发工具配置为仅遵循第一父路径并忽略所有这些中间提交。例如,there is no --first-parent argument to git bisect。另外,我对Jenkins不太熟悉,知道将它配置为优先构建和测试所有其他提交的第一个父路径是多么容易。

答案 1 :(得分:5)

最后,它主要是个人品味问题......只能解释我的品味(并为其提供一些理由)。

我倾向于保持个人提交,即使他们只是“修复愚蠢的拼写错误”。任何“历史重写”都会创建前所未有的提交,因此保证永远不会被测试。此外,最小的提交会使git bisect在以后出现错误时非常有用。最好能够将其缩小到一些变化的线,而不是一周的工作,压扁在一起。

如果一个开发分支得到了一个混乱的历史,我清理它(最低限度,即,恢复提交从未发生过,一般修复,如空格或变量重命名可能早先应用,一些重新排序将相关的变化放在一起)。提交仍然很小,很少被压扁。这种清理我主要是逐步完成的。然后我将清理过的分支与“官方”分支合并(或变基)。