“git merge --squash”的正确用例是啥?

Posted

技术标签:

【中文标题】“git merge --squash”的正确用例是啥?【英文标题】:What are the proper use cases of "git merge --squash"?“git merge --squash”的正确用例是什么? 【发布时间】:2019-11-30 08:57:04 【问题描述】:

有人喜欢git merge --squash,原因如下:

压缩到单个提交使您有机会清理混乱的 WIP 提交,并为您正在合并的更改提供一个很好的理由。

https://coderwall.com/p/qkrmjq/git-merge-squash

但是,我认为有一些缺点超过了制作干净历史的优点。

    git merge --squash 产生非合并提交。因此,Git 不会将您要合并的提交识别为合并基础。这会导致不需要的合并结果:1)在分支 X 上将 A 更改为 B,2)git merge --squash 从分支 X 到分支 Y,3)在分支 X 上将 B 更改为 A(还原),以及 4)将 X 合并到 Y . 在步骤 4 之后,在分支 Y 上,从 A 到 B 的更改不会恢复。在这里,这是 3 路合并,因此比较从分支 X 到合并基础的差异和从分支 Y 到合并基础的另一个差异。前者包括没有变化,后者包括从A到B的变化,所以合并结果包括从A到B的变化。

    提交作者被覆盖,这会丢弃贡献。 git merge --squash 生成一个新的提交,其名称为 git merge --squash。当然,提交内容来自原始提交。这听起来像是在窃取贡献。这成为https://github.com/Microsoft/winfile/pull/42#issuecomment-380681627 中的一个问题

git merge --squash 的正确用例是什么?

【问题讨论】:

这篇文章围绕着类似的优缺点展开:reddit.com/r/git/comments/9g0kjv/… 【参考方案1】:

git merge --squash 的正确用例是什么?

    如果项目的策略是不允许在其主分支上进行合并提交,那么创建非合并提交这一事实就不是问题(这正是您想要的)。

    如果您不打算在合并后再次使用 Y 分支(例如,因为 Y 是一个短暂的功能分支,并且该功能现在已合并到 X),那么未来从 Y 合并具有“错误的“合并基础。无论如何,你不会再从 Y 做任何未来的合并。

    或者,如果您在合并后将分支 Y 重新设置在 X 上,那么来自 Y 的未来合并将具有正确的合并基础。

    如果分支上的所有提交都是同一作者,那么第二个问题也不存在。

所以它可能不是在所有情况下都有用,但肯定有一些情况下它完全可以使用。最明显的一个是在本地分支进行 WIP 提交,然后将它们推送到其他开发人员可以看到的地方。分支 Y 上所有混乱的 WIP 提交都是由同一作者提交的,没有其他人会看到分支 Y,因此可以在合并后将其重新定位到 X 上,或者即使您不感兴趣,也可以完全丢弃 Y在 WIP 历史中。

【讨论】:

【参考方案2】:

这个例子似乎是故意设计来展示缺点的。如果 squash-merge 适用于 Branch X,则步骤 3 和 4 可能是 git merge BranchX -n && git commit --amendgit checkout BranchA && git reset HEAD^ --hard && git merge BranchX --squash && git commit,就好像 BranchX 是 squash-merged 而不是被合并两次。

messy WIP commits 通常位于本地临时主题分支上。这些提交的作者通常是要执行 squash-merge 的同一个人。这些提交以更随意的方式创建为草稿,稍后 squash-merge 可以将它们转换为单个优雅的提交,就好像它是在目标分支上精心创建的一样。

有时,为了保持线性历史,人们可能会将一个正式分支压缩合并到另一个正式分支,而不是执行真正的合并。压扁的提交是由不同的作者创建的。捐款可能会被盗。但在实践中,原始分支和带有提交消息的提交哈希按照约定保存在新提交的消息中,合并后的分支也被保留,以便人们了解 squash-merge 提交的来源并能够查看原始提交。

【讨论】:

以上是关于“git merge --squash”的正确用例是啥?的主要内容,如果未能解决你的问题,请参考以下文章

git中的merge --squash

git merge --squash 选项合并commit操作实例

git merge时merge/squash merge/rebase merge的区别

聊下git merge --squash

聊下git merge --squash

git merge的三种操作merge, squash merge, 和rebase merge