git如何处理squash merge和normal merge?

fslejnso  于 2024-01-04  发布在  Git
关注(0)|答案(2)|浏览(133)

假设我们有一个合并请求,将来自分支A的提交合并到分支B中,我们可以使用普通合并和挤压合并来执行合并。(所有的提交都会合并成一个提交),然后从分支A向分支B提交另一个类似的PR,为什么git仍然允许以正常的方式合并(所有的提交都会被保留)?我的意思是修改已经被合并到分支B中了,为什么在第二次合并的时候没有引起任何冲突呢?

dm7nw8vv

dm7nw8vv1#

当你使用squash的时候,git保留任何关于合并的提交的信息(可能除了注解),所以与真实的merge不同,git不知道 * 原始的 * 分支已经被合并了。这就是为什么当你处理长时间运行的分支时,不建议使用squash。
在真实的合并中,已经合并的两个分支之间的共同祖先发生了变化,但是在挤压合并中,共同祖先不会移动,因此两个分支之间的后续合并将容易产生冲突,或者是在先前的挤压合并中处理的冲突,或者是新的冲突。
为了用图形来解释它,假设你有这样的初学者:

* GGG blah blah (other-branch)
  * FFF
  * EEE
* | DDD (main)
* | CCC
* | BBB
|/
* AAA

字符串
现在,最新的共同祖先是什么?AAA,对吗?
现在,假设你做一个 * 真实的 * 合并,我们得到这样的东西:

* HHH (main)
|\
| * GGG (other-branch)
| * FFF
| * EEE
* | DDD
* | CCC
* | BBB
|/
* AAA


很好。最近的共同祖先是什么?

答案提示:它是GGG。在继续之前,请确保您消化它。

现在,假设你继续在 * 两个 * 分支上工作,最后得到这样的结果:

* NNN (main)
* MMM
* LLL
| * KKK (other-branch)
| * JJJ
| * III
* | HHH
|\|
| * GGG
| * FFF
| * EEE
* | DDD
* | CCC
* | BBB
|/
* AAA


如果你再次合并 *,git需要考虑最后一个共同祖先之后的变化,我们已经知道是GGG,对吧?所以,git需要考虑合并:

* NNN (main)
* MMM
* LLL
| * KKK (other-branch)
| * JJJ
| * III
* | HHH
|/
* GGG


现在,让我们回过头来看看如果我们使用squash-merge的话会怎么样。在第一次squash-merge之后,我们会得到:

* HHH squash merge (main)
| * GGG (other-branch)
| * FFF
| * EEE
* | DDD
* | CCC
* | BBB
|/
* AAA


那么,现在.

* NNN (main)
* MMM
* LLL
| * KKK (other-branch)
| * JJJ
| * III
* | HHH squash merge
| * GGG
| * FFF
| * EEE
* | DDD
* | CCC
* | BBB
|/
* AAA


如果你尝试合并,git将不得不重新开始考虑来自AAA的更改,而不是GGG,因为它发生在以前.(这使得它们与git的bits * 不同 *),那么你会得到一堆冲突.(每个分支上的内容与原来的冲突会有一点不同,实际上.但它将是 * 相同的代码段 加上 * 一些.只是为了好玩。
所以,总而言之.
现在,关于没有任何冲突:如果被合并的分支中有 * 完全 * 相同的更改,git * 不会 * 产生冲突.(没有额外的变化)然后到git,同样的东西来自两个分支,所以没关系。(就像cherry-picking)当git抱怨cherry-pick操作没有引入任何真实的 * 更改时,你需要决定怎么做(跳过它,create am empty commit).这是一个我想看看git是否不会抱怨并允许合并就像那样进行的场景。

5vf7fwbs

5vf7fwbs2#

.如果我们先用squash merge进行合并(所有的提交都会被合并成一个提交),然后再提交另一个类似的PR.为什么git仍然允许以正常的方式进行合并(所有的提交都会被保留)?
重申一下这个问题--首先你用squash合并一个分支,然后你用普通的合并再次合并同一个分支。
在第一个PR和squash merge之后,你应该观察到第二个PR带来了一堆提交 * 但没有文件更改 *。这就是为什么没有任何冲突,因为如果状态没有变化,你就不会有冲突。它“允许”你这样做的原因是,当你合并的时候,你带来了新的提交,有时候,即使状态没有变化,这样做也是有意义的。一个常见的场景是,当你决定从开发分支中挑选一些提交时,到一个发布分支中,这样可以更快地部署它。之后,您可以将发布分支合并回开发分支,以确保它保持同步,但是由于这些变化已经在两个分支中,合并只带来了新的提交ID,而没有任何实际的变化。
顺便说一句,在同一个分支的压缩合并之后再进行非压缩合并是没有意义的。(常规合并)或不合并(squash merge)。然后只选择一个。也许只有在squash merge之后对相同的分支执行常规合并才有意义,如果你已经做了squash合并,然后后悔了,然后意识到你想保持提交的粒度。注意相反的情况是不正确的;在常规合并之后故意挤压合并相同的分支是没有意义的,因为挤压合并实际上将添加零值,没有新内容,也没有要合并的现有提交。

相关问题