git合并壁球和反复出现的冲突

dra*_*nHR 20 git version-control git-merge git-branch

我有一个git存储库masteralt分支.alt分支包含修改后的master代码版本,我正在尝试将更改合并masteralt这样:

git merge --squash master
Run Code Online (Sandbox Code Playgroud)

合并导致冲突:

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.
Run Code Online (Sandbox Code Playgroud)

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

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

Use*_*ess 34

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

也就是说,工作树具有您期望的修改,但元数据不会:关键的是,提交没有两个父项(一个打开master,一个打开alt),因此后续合并无法找出最后一个公共祖先.


有用的用途 squash

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

无用的 squash

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

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

  • 仅仅因为"壁球"不能做OP想要的,并不意味着它没有_no_使用.如果你从一个已完成的功能分支一次性合并回到`master`并且再也不想使用该功能分支(并且不想保留该功能的增量开发历史记录),那就太棒了 (4认同)
  • 如果您不喜欢它,请不要使用它.我已经看到了很多功能分支,我希望这些功能可以减少真实变化; 重新定位是一种方法(将数十个小提交压缩成一个值得阅读的提交).请注意,我不在乎是否有其他人想要保留他们的旧功能分支用于考古目的,但是我不会从他们将其吸入共享的`master`时间线中获得任何好处. (4认同)
  • 我想说的是,最好将 git 的历史记录与您的行为历史记录保持一致。如果你合并了,让 git 也知道它,否则将来你或 git 都会感到困惑。出于同样的原因(重写历史),我也不喜欢 `git rebase`。 (3认同)
  • `--squash` 选项看起来很_无用_。 (2认同)
  • 我不确定.你会_think_功能分支完成,但是_always_某处有一点小错误或需要一个小修补.我不明白的是,你为什么不想要历史?携带历史的合并节点是否会以任何方式伤害任何人? (2认同)

Von*_*onC 22

添加到“挤压合并的无用用途”:Git 2.29(2020 年第 4 季度)通过以下方式说明了陷阱merge --squash

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

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

签字人:brian m. 卡尔森

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

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

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

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

合并和变基


当使用挤压合并合并长期存在的分支时,会出现什么类型的问题?

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

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

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

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

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