39

我有一个带有分支master的git 存储库。分支包含修改后的代码版本,我正在尝试将更改从到合并为:altaltmastermasteralt

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再次运行(不对任何分支进行任何更改)时,我会得到相同的冲突错误。

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

4

2 回答 2

51

通过squash合并,您创建了一个提交,它具有合并的效果,但不是真正的合并。

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


有用的用途squash

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

无用的用途squash

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

squash只是不是一个很好的默认值,这就是为什么它不是默认值。

于 2012-08-03T14:43:03.700 回答
9

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

请参阅brian m的提交 087c616提交 409f066提交 5065ce4(2020 年 9 月 20 日) 。卡尔森 ( bk2204) .
(由Junio C Hamano 合并 -- gitster--提交 c5a8f1e中,2020 年 9 月 29 日)

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

签字人:brian m. 卡尔森

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

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

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

gitfaq现在在其手册页中包含:

合并和变基


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

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

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

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

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

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

于 2020-10-01T16:20:57.587 回答