git合并壁球和反复发生的冲突

Posted

技术标签:

【中文标题】git合并壁球和反复发生的冲突【英文标题】:git merge squash and recurring conflicts 【发布时间】:2012-08-01 15:08:38 【问题描述】:

我有一个带有 masteralt 分支的 git 存储库。 alt 分支包含 master 代码的修改版本,我正在尝试合并从 masteralt 的更改,如下所示:

git merge --squash master

合并导致冲突:

Auto-merging myproject/foo/bar
CONFLICT (content): Merge conflict in myproject/foo/bar
Squash commit -- not updating HEAD
Automatic merge failed; fix conflicts and then commit the result.

在我解决冲突并提交更改后,一切似乎都很好,但是当我再次运行 git merge --squash master(不对任何分支进行任何更改)时,我会得到同样的冲突错误。

这是为什么呢?我错过了什么?

【问题讨论】:

--squash 不会真正合并分支,但会从中创建一个提交(然后合并)。阅读手册页还表明在git merge --squash 之后没有提交 【参考方案1】:

通过squash进行合并,您创建了一个具有合并效果但实际上不是合并的提交。

也就是说,工作树具有您所期望的修改,但元数据没有:至关重要的是,提交没有两个父级(一个在 master 和一个在 alt),因此后续合并无法找出最后一个共同祖先。


squash 的有用用法

    完全完成功能分支合并到master。我会将任何有用的信息累积到压缩的提交中,但特别是不希望此功能的增量开发历史污染master 提交时间线。 将几个独立的功能(或来自不同开发人员的贡献)合并到同一个集成分支上,同样不保留它们的增量历史记录。我可以将它们全部变基,然后使用rebase -i 压缩它们的提交,但这更容易

squash 的无用用法

您希望保持历史和祖先元数据完整的任何合并,例如您希望重复递归合并正常工作的任何时候,特别是 OP 正在尝试做

squashjust 并不是一个很好的默认值,这就是它不是默认值的原因。

【讨论】:

--squash 选项看起来很无用 仅仅因为squash 没有做 OP 想要的,并不意味着它有 no 用途。如果您将完成的功能分支一次性合并回master,并且再也不想使用该功能分支(并且对保留该功能的增量开发历史不感兴趣),那就太好了 我不太确定。您会认为功能分支已完成,但总是某处存在小错误或需要进行小修复。我不明白的是,你为什么不想要历史?合并节点,承载历史,是否以任何方式伤害任何人? 如果您不喜欢它,请不要使用它。我已经看到了很多我希望有更少的噪音来掩盖真正的变化的功能分支;变基是一种方法(将数十个微小的提交压缩成一个值得阅读的内容)。请注意,我不在乎其他人是否想出于考古目的保留他们的旧功能分支,但我从他们将其吸入共享的 master 时间线中获得任何好处。跨度> 我想说的是,最好让git的历史和你的行动历史保持一致。如果你合并了,让 git 也知道它,否则将来你或 git 都会感到困惑。出于同样的原因(重写历史),我也不喜欢git rebase【参考方案2】:

添加到“壁球合并的无用用途”:Git 2.29(2020 年第四季度)用merge --squash 说明了陷阱:

参见brian m. carlson (bk2204) 的commit 087c616、commit 409f066、commit 5065ce4(2020 年 9 月 20 日)。(由 Junio C Hamano -- gitster -- 合并到 commit c5a8f1e,2020 年 9 月 29 日)

docs: 解释为什么 squash 合并会被长时间运行的分支破坏

签字人:brian m.卡尔森

在许多项目中,通常使用 squash 合并,主要是为了在不使用逻辑独立、可对分提交的开发人员面前保持整洁的历史记录。

尽管这种情况很常见,但由于缺少任何新的合并基础,当使用 squash 合并来合并长时间运行的分支时,这往往会导致严重的问题。

即使是非常有经验的开发人员也可能犯这个错误,所以让我们添加一个常见问题解答条目,解释为什么会出现问题,并解释应该使用常规合并提交来合并两个长期运行的分支。

gitfaq 现在包含在其man page 中:

合并和变基


用 squash 合并合并长寿命分支时会出现哪些问题?

一般来说,在使用 squash 时会出现各种各样的问题 merges 多次合并两个分支。 这些可以包括看到额外的 在 git log 输出中提交,使用 GUI,或者在使用 ... 表示法时 表达范围,以及需要重新解决冲突的可能性 一次又一次。

当 Git 在两个分支之间进行正常合并时,它只考虑三个 点:两个分支和第三个提交,称为 merge base,即 通常是提交的共同祖先。 合并的结果是总和 合并基础和每个头部之间的变化。

当你合并两个 具有常规合并提交的分支,这将导致新的提交 当它们再次合并时最终成为合并基础,因为现在有一个新的 共同祖先。 Git 不必考虑在 合并基础,因此您不必重新解决之前解决的任何冲突。

执行 squash 合并时,不会创建合并提交;相反, 来自一侧的更改将作为常规提交应用到另一侧。 这意味着这些分支的合并基础不会改变,所以当 Git 去执行它的下一次合并,它考虑它的所有更改 考虑了最后一次加上新的变化。 这意味着可能需要重新解决任何冲突。 同样,在 git diffgit log 或 GUI 中使用 ... 符号的任何内容都将导致显示自原始合并基础以来的所有更改。

因此,如果你想重复合并两个长期存在的分支,那就是 最好始终使用常规合并提交。

【讨论】:

以上是关于git合并壁球和反复发生的冲突的主要内容,如果未能解决你的问题,请参考以下文章

Git:如何避免在先前合并还原后合并功能分支时发生冲突

git 解决冲突

Git 合并冲突之后怎么办?

如何解决Git中的合并冲突

究竟是什么导致了git中的合并冲突?

解决 Git 冲突的 14 个建议和工具