“git merge --squash”的正确使用案例是什么?

11

有些人喜欢使用git merge --squash的原因如下:

将多个提交压缩为一个提交可以清理杂乱的WIP提交,并为您正在合并的更改提供充分的理由。

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

然而,我认为这种方法的缺点超过了生成干净历史的优点。
1. git merge --squash 生成了一个非合并提交。因此,Git 将不会将你正在合并的提交识别为合并基础。当在分支 X 上将 A 修改为 B,执行 git merge --squash 合并分支 X 到分支 Y ,再在分支 X 中将 B 修改为 A(还原),然后将分支 X 合并到分支 Y 时,这会导致不希望看到的合并结果。 enter image description here 在第四步之后,在分支 Y 上,从 A 到 B 的更改并未还原。由于这是三方合并,所以会比较从分支 X 到合并基础和从分支 Y 到合并基础的差异。前者没有变化,而后者包含从 A 到 B 的变化,因此合并结果包括从 A 到 B 的变化。
2. 提交作者被覆盖,这样就无法贡献代码。 git merge --squash 生成一个新的提交,且该提交的名字是进行 git merge --squash 的人。当然,提交内容来自原始的提交。这听起来像是窃取了其他人的贡献。这在 https://github.com/Microsoft/winfile/pull/42#issuecomment-380681627 中成为了一个问题。

git merge --squash的正确使用场景是什么?


这篇文章围绕着类似的优缺点展开讨论:https://www.reddit.com/r/git/comments/9g0kjv/what_are_the_pros_or_cons_of_squashing_before/ - nitishagar
2个回答

6

git merge --squash 的适用场景是什么?

  1. 如果项目规定主分支不允许合并提交,那么创建非合并提交就没有问题(这正是你想要的)。

    如果你在将分支 Y 合并到 X 分支后不再使用分支 Y(例如,因为 Y 是一个短期功能分支,该功能现在已经合并到 X 分支中),那么未来从 Y 分支进行合并所使用的"错误"合并基础是无关紧要的。无论如何,您都不会再从 Y 分支做任何未来的合并。

    或者,在合并后,将分支 Y 基于 X 进行变基,则未来从 Y 分支进行的合并将具有正确的合并基础。

  2. 如果分支上的所有提交都是由同一作者进行的,则第二个问题也不存在。

因此,在不是所有情况下都有用,但肯定存在一些可以完全使用它的情况。最明显的一种情况是,在推送给其他开发人员之前用于制作 WIP 提交的本地分支。分支 Y 上的所有混乱的 WIP 提交都是同一作者提交的,并且没有其他人会看到分支 Y,因此可以在合并后将其基于 X 进行重命名,或者干脆将 Y 分支删除,即使您也对 WIP 历史不感兴趣。


但是为什么不直接压缩“脏”提交并合并(现在已经压缩的)分支呢?一个好的开发者应该将一个功能拆分成多个步骤,以记录开发过程并允许有意义的审查(例如通过不将开发工作与必要的重构相结合),如果整个分支被压缩,则这些信息会丢失。 - HappyDog
1
你假设这个功能足够复杂,需要多个步骤。也许你添加了一个单元测试,修复了一个错误,并添加了另一个单元测试。在合并后保留三个单独的提交真的有意义吗?我可能会将它们压缩成一个提交,但我不认为这意味着我不是一个“像样的开发者”。对于更大的功能分支,历史记录当然很有用,但这不是git分支的唯一用途。 - Jonathan Wakely
我从不做出没有例外的硬性规定,也不会做出任何假设。然而,这是一种明显的代码异味。如果它们是三个独立的事物,那么它们应该分别记录并显示为三个单独的提交。如果它们是同一个问题的三个部分,我可能会一次性提交它们,但如果你错过了这个机会,把它们压缩到分支中可能是一个理由,只要你给出适当的提交消息,而不是一些自动生成的混乱。无论哪种方式,这都应该在审查之前完成,而不是作为合并的一部分。 - HappyDog

4
该示例似乎故意设计成展示缺点。如果拿来用于X分支,步骤3和4可以改为git merge BranchX -n && git commit --amend或者git checkout BranchA && git reset HEAD^ --hard && git merge BranchX --squash && git commit,就像是将BranchX压缩合并一次而不是两次。
"混乱的WIP提交"通常在本地临时主题分支上。这些提交的作者通常是将要执行压缩合并的同一个人。这些提交以更随意的方式作为草稿创建,稍后压缩合并可以将它们转换为单个优雅的提交,就好像是仔细地在目标分支上创建了它们。
有时为了保持线性历史,人们可能会将一个正式分支压缩合并到另一个分支,而不是进行真正的合并。压缩的提交由不同的作者创建。原始分支和提交哈希值与提交消息按惯例保留在新提交的消息中,并且合并的分支也得以保存,以便人们了解压缩合并提交的来源,并能够查看原始提交。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接