压扁的提交是否与其原始提交冲突

Do squashed commits conflict with their original commits

以下情况是否会产生冲突,需要手动解决?

  1. 您为 PR 提交了一个功能分支,其中包含提交 D、E。

  2. 在审查 PR 的同时,您继续在本地处理同一功能分支,并添加更多提交 F、G、H。

  3. 在某些时候,PR 被批准并合并到 master 中。 Commits D/E on master have been replaced with commit X due to squashing。您现在有一个包含提交 D、E、F、G、H 的本地分支和一个包含提交 X 的主分支。

  4. 您想将提交 F/G/H 合并到 master 中。因此,您尝试将本地分支(包含 D/E/F/G/H)合并到 master(包含 X)中。

提交 D/E 和 X 涉及完全相同的代码行,但具有不同的提交 ID。如果把 D/E 放在一起看,和 X 比较,它们是相同的。但是如果孤立地看 D 并与 X 进行比较,它们之间存在许多差异,在共同修改的行上。

git 是否足够聪明,可以在没有任何合并冲突的情况下合并 {D/E - X}?还是上面会产生很多冲突需要人工干预?

Git 比较自共享基础以来每个提示的变化。相同的更改不会导致冲突。

我 运行 在本地进行一些 git 实验,复制问题中描述的工作流程步骤。不幸的是,答案似乎是肯定的。使用 git squash 会导致许多合并冲突,如果你不小心你在做什么的话。

我在 this blog post.

中广泛地写过这个

如果您在没有任何压缩的情况下进行简单的合并,就不会发生上述问题。在这种情况下,合并后,master 和本地 b运行ch 都将包含提交 D-E。因此,下次您尝试合并本地 D-E-F-G-H b运行ch 时,git 将通过在 master 之上应用 F-G-H 来简单地执行合并。

但是,因为我们做了壁球,所以结果很混乱 git。它不是简单地在 X 之上应用 F-G-H,而是尝试将 D-E-F-G-H 与 X 合并在一起。不幸的是,因为提交 F-G-H 修改了同样被 X 修改的代码行,结果差异因合并冲突而失败。

解决此问题的一些潜在方法:

  1. 蛮力:吸干并手动解决所有冲突。

  2. 提交拉取请求后,请勿在拉取请求中包含的提交之上开发任何其他提交。从 git 的角度来看,拉取请求中的那些提交将消失,因此您不想依赖它们。不幸的是,这意味着您想要在刚刚提交的内容之上进行的任何改进都需要等到您的拉取请求被批准并合并。

  3. 如果您在较早的拉取请求的基础上进行了改进,请不要合并较早的拉取请求。相反,使用更新后的 b运行ch 提交新的拉取请求,或者用您所做的所有改进覆盖现有的拉取请求。不幸的是,这使得拉取请求过程变得孤注一掷。理想情况下,您可能希望初始拉取请求和额外的改进是 approved/merged 递增的。相反,为了防止冲突,您将不得不强迫自己一次性合并所有内容,或者根本不合并任何内容。

  4. 假设您之前的 PR 已合并,并且您有新的改进现在也想合并到 master 中。与其尝试将整个 b运行ch 合并到 master 中,不如挑选您创建的增量提交,并仅合并那些精心挑选的提交。因此,在上面给出的示例中,不是尝试将 D-E-F-G-H 合并到 X 中,而是 cherry pick 提交 F-G-H,将它们应用到 X 之上,然后使用生成的 b运行ch 创建拉取请求。这很有效,避免了所有冲突,并允许您在任何 time/pace 您想要的地方进行开发工作。不幸的是,这还需要您手动跟踪 D-E == X 的事实,并且之后的提交 F-G-H 需要手动挑选和应用。这需要您付出更多的时间和认知努力,并且也很容易通过挑选过多的提交(并且无论如何都会产生冲突)或挑选太少的提交(并且遗漏重要的更改)来搞乱这一步。

  5. 避免使用 github 的 squash-on-megre 功能。在提交拉取请求之前,要么在本地压缩所有提交。或者合并拉取请求而不进行任何压缩。这是大多数项目的现状,随之而来的是所有 benefits/downsides。

如您所见,在合并之前压缩所有提交确实存在 problem/cost,并且上述解决方案中的 none 是完美的。我不确定以上哪一项是所有邪恶中最少的。但我确实想鼓励您更深入地思考这个问题,并意识到利用这个令人敬畏的新 GitHub 功能所涉及的注意事项。