为什么挑选特定的提交会导致代码库不稳定?

7

我不是开发人员。 在我们的一个项目中,由于很多问题需要时间来解决,我们一直在挑选提交记录,现在我们必须经常这样做。 有位开发人员告诉我应该避免使用挑选提交记录功能,因为这会使仓库不稳定。 那是什么意思,它怎么会使仓库不稳定? 换句话说,挑选提交记录的负面影响是什么?


要明确的是,挑选提交并不会对存储库造成任何损害。但它可能会混淆您的开发过程。 - Schwern
通常情况下,当出现问题时需要进行挑选,例如,有一次某个开发人员在不加思考的情况下将一些错误/不完整的代码合并到生产分支中,因此我不得不从坏提交中挑选好的提交,那是我唯一使用挑选功能的时候,但如果您经常使用它,那就意味着流程存在问题。 - Aurangzeb
2个回答

7
要明确的是,挑选不会损害您的存储库。Git 对挑选操作没有问题。但是,挑选可能会使您的代码不稳定。
挑选基本上是将提交复制到另一个分支。如果小心使用,这是非常有用的工具。如果草率使用,则会复制未经测试的代码。如果您发现自己经常需要使用挑选操作,则您的过程可能存在某些次优因素。
一个典型的例子是当你有一个既包含新功能又修复了一个bug的大型特性分支。那个特性需要很长时间才能完成,但现在你需要那个bug修复。(更深层次的问题是为什么那个特性分支需要这么长时间?它太大了吗?可以将其拆分成一系列较小的特性吗?)
你的代码库看起来像这样。
A - B - C - D - E [master]
     \
      1 - 2 - bugfix - 3 - 4 - 5 [feature]

接下来会根据您的工作流程而定。您可以直接将其挑选到主分支master中。
git cherry-pick bugfix

A - B - C - D - E [master]
     \
      1 - 2 - bugfix - 3 - 4 - 5 [feature]

这样直接将未测试的代码提交到主分支master中存在所有问题。它可能依赖于某个其他的feature,也可能无法正常工作,会引入更加微妙的错误,或者是不完整的。这很可能就是他们所说的“使代码不稳定”。
更好的做法是遵循"特性分支"工作流程。禁止直接向master提交代码,一切都必须在分支上完成。分支经过QA测试后再合并。这确保了master始终保持在良好的状态,并且没有人共享未测试和低质量的代码。
您可以为错误修复打开一个新的分支,并在其中挑选它。
git checkout -b fix/bug
git cherry-pick bugfix

                  bugfix' [fix/bug]
                 /
A - B - C - D - E [master]
     \
      1 - 2 - bugfix - 3 - 4 - 5 [feature]

然后,fix/bug 经过正常的 QA 流程。任何问题都会被修复。当它通过 QA 后,它将被合并到 master 分支中。假设出现了问题,因此有另一个提交。
git checkout master
git merge fix/bug
git branch -d fix/bug

                  bugfix' - F
                 /           \
A - B - C - D - E ----------- G [master]
     \
      1 - 2 - bugfix - 3 - 4 - 5 [feature]

现在,feature 应该从 master 更新自己,以确保它拥有完整的错误修复。可能会存在 master 版本的错误修复与其自身版本之间的冲突。像往常一样解决它们。
git checkout feature
git merge master

                  bugfix' ---- F
                 /              \
A - B - C - D - E -------------- * [master]
     \                            \ 
      1 - 2 - bugfix - 3 - 4 - 5 - * [feature]

一旦feature完成,它可以像正常情况下一样合并到master中。Git不关心历史记录中有两个版本的错误修复,任何问题都已经在更新合并中解决了。

git checkout master
git merge feature
git branch -d feature

                  bugfix' ---- F
                 /              \
A - B - C - D - E -------------- * --------- * [master]
     \                            \         /
      1 - 2 - bugfix - 3 - 4 - 5 - * - 6 - 7

顺便提一下:如果你使用rebase来更新你的分支,而不是合并,这是我的偏好,Git可能会认为一个修复bug的提交是多余的,因此会将其完全删除。

git checkout feature
git rebase master

                  bugfix' - F
                 /           \
A - B - C - D - E --------- - * [master]
                               \
                                1 - 2 - 3 - 4 - 5 [feature]

1
“而且你正在复制未经测试的代码”…为什么挑选代码和代码是否经过测试有任何关系呢? - Tim Biegeleisen
1
@TimBiegeleisen 用得很草率... 即从一个分支中获取提交并将其粘贴到主分支上的情况,我概述了这种情况。 - Schwern

6
Git cherry-picking通常用于将一个分支的提交带到另一个分支,因为通常做法(例如合并或变基)不可用。通常合并选项可能不适用,因为一个功能分支还没有准备好并入其源分支。然而,可能需要立即在源分支中使用某个提交,例如用于修复错误或其他紧急情况,因此cherry-picking是一种方法。
Cherry-picking实际上并不会使存储库“不稳定”,但是它确实存在重复提交的风险。回到功能分支具有需要立即返回源的提交的示例,如果我们稍后合并此功能分支,则可能会带入已经通过cherry-pick的相同提交。因此,源分支可能会有多个执行相同功能的提交。这并不会使存储库不稳定,但确实会导致历史记录难以阅读。未来,历史记录的读者可能会发现很难弄清楚贡献者正在做什么以导致出现重复提交。
这个问题的根源在于Git cherry-pick每次使用时实际上会创建一个新的提交,具有新的SHA-1哈希值。因此,将一个功能分支中的单个提交cherry-picking到源中实际上会留下两个提交,即使它们在功能上是相同的,但其SHA-1哈希值完全不同。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接