Squash 合并会在“我们的”分支(在您的情况下为 master)上创建一个新提交,以引入“他们的”分支(开发)的更改就好像您已将两者合并。它实际上并没有创建合并(将两个分支联系在一起的多父提交);如果这样做,那将只是一次常规合并。所以 git 之后无法判断来自开发的提交是否等于添加到 master 的新提交。
我想我还没有看到正确的用例,但我发现 squash 合并有点毫无意义。据我所知,合并和变基之间两全其美。
更新 - 基于 cmets 的一些说明可能会有所帮助...
所以我们知道,常规合并是具有两个或多个父级的单个提交。它的第一个父级是来自合并的“我们的”分支(假设是 master),而我们合并的分支是附加的父级。单个提交就是添加到 master 的全部内容。
A ---- B - M
/
X ---- Y
所以这似乎是错误的,因为git log 将分别显示 A、B、X 和 Y。这是默认行为,因为它向您展示了更改是如何真正引入的。
您可以通过说git log --first-parent 获得更线性的视图,但log 仍然不想显示合并补丁 (meh),因此它不像您那样看起来像线性历史' d 从 squash 或 rebase 中获取。
但M^ 肯定等于B,所以从大师的角度来看,M 是一个单一的提交,它引入了来自分支的所有更改。如果您还希望它记录 X 和 Y 的更改可以从 M 访问,那么这就是 git 提供的方式。
现在你可能已经发现我不太喜欢merge --squash,所以原因如下:
假设我进行了 squash 合并,而不是上图所示的常规合并。为了清楚起见,我将添加一个共同的祖先 O:
O ---- A ---- B ---- XY <--(master)
\
X ---- Y <--(development)
现在在开发方面进行了更多工作
O ---- A ---- B ---- XY <--(master)
\
X ---- Y ---- Z <--(development)
那么我如何最好地将 Z 合并到我的主分支中?
如果我将 Z 定期合并到 master 中,那么 git 会知道 Y 是 Z 和 M 的共同祖先(但我没有 M;我做了一个壁球所以我有 XY),我可以毫无问题地进行另一个合并。
如果我将我的开发分支重新定位到 master,我会拥有
O ---- A ---- B ---- X' ---- Y' <-- (master)
\
Z <-- (development)
这也没关系,只要我的 rebase 没有弄乱其他任何人的历史(如果 X 和 Y 已经发布,它可能会这样,但那完全是另外一罐蠕虫)。
在这两种情况下,我都可以毫无问题地进行另一次合并或变基。但是通过进行壁球合并,我将 git 混淆为看到两个没有良好记录关系的历史,所以除非我一直指向 Y,否则我不走运
O ---- A ---- B ---- XY <--(master)
\
X ---- Y ---- Z <--(development)
^- (last_merge)
而且,正如您所注意到的,如果您走这条路,git status 将永远感到困惑。