10

我真的相信在一个问题上进行一次提交是一种很好的做法。我确定我在“最佳实践”之类的文章中某处读过它。

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

  • 对于一个新问题,我使用git checkout -b new-issue.
  • 将所有更改提交给它。有时这涉及大量提交。
  • 完成后,我squash将提交并将rebase它们放入当前的主题分支。
  • 如果出现问题,我可以git revert提交,找到错误,修复它,然后将新补丁提交到主题分支。我不会更改远程存储库的历史记录。

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

  • 为新问题创建新分支。
  • 将一切都投入其中。
  • 用于merge --no-ff将问题分支与主题分支合并(因此我们将拥有我们可以的“合并提交” revert)。
  • 如果出现问题,我们可以使用它git bisect来查找错误。

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

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


  • 您认为这两种方法的优缺点是什么?

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

  • 在实践中,你真的习惯于git bisect寻找错误吗?(我没有……)

4

2 回答 2

9

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

  1. 创建一个新的主题分支
  2. 做一堆提交
  3. 在合并回父分支之前,清理提交:
    • 重新定位到父分支的最新版本
    • 壁球错字修复提交
    • 将一次执行多项操作的提交拆分为单独的提交
    • 重新排序提交以使审阅者更容易理解更改的顺序
    • 等等
  4. 合并--no-ff到父分支

上述步骤会生成如下所示的历史记录:

*   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)。
  • 提交的更精细粒度使得更容易弄清楚为什么进行特定更改,这有助于区分意外更改和有意但微妙的更改。
  • 如果多个人在分支上进行了协作,您可以看到他们都是谁以及每个人贡献了多少。
  • 合并主题分支上的提交数量让您大致了解更改了多少。
  • 提交的时间范围可以提供有用的上下文。
  • 您可以轻松地挑选对不同分支进行的特定更改(例如,挑选将错误修复到发布分支所需的最小更改)。

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

于 2013-03-30T17:36:39.450 回答
5

最后,这在很大程度上是个人品味问题......只能解释我的品味(并为此提供一点理由)。

我倾向于保留个人提交,即使它们只是“修复愚蠢的错别字”。任何“历史重写”都会创建以前从未存在过的提交,因此保证从未经过测试。git bisect此外,当稍后出现错误时,最少的提交会非常有用。最好能够将其缩小到几条更改的行,而不是把一周的工作挤在一起。

如果开发分支的历史记录一团糟,我会清理它(最低限度,即从未发生过恢复的提交,可能会更早应用空格或变量重命名等一般修复,一些重新排序以将相关更改放在一起)。提交仍然很小,很少被压扁。这种清理我主要是逐步进行的。然后我将清理后的分支与“官方”分支合并(或变基)。

于 2013-03-21T19:10:36.853 回答