不合并压缩与合并压缩选项的提交差异

24

我日常使用SmartGit作为客户端选择。但是我的团队成员们坚持使用git原生的非商业GUI。我们发现了我们的合并提交看起来有些不同。

SmartGit在请求合并分支时提供以下选项: SmartGit commits type

下面的图表显示了我的示例SmartGit图表输出,包括:

  • 单个 master 分支
  • 一个分支通过 合并提交 选项合并到主分支
  • 一个分支通过 简单提交 选项合并

其中一个分支(with_merge_branch)通过线条将分支与主分支连接起来来可视化合并操作。第二个分支(normal_commit_branch)则没有。

git tree

问题是,如何通过原生git命令强制实现这两种行为?也就是说,这两个提交之间有什么区别?


可能是以下问题的重复:在 Git 中,merge --squash 和 rebase 有什么区别? - Tim Biegeleisen
2
我从未使用过它,但是使用git合并时选择压缩选项会删除第二个父分支的任何痕迹。如果您遵循重复链接,您将看到一些使用它的原因示例。不使用压缩选项进行合并是git merge的默认行为。 - Tim Biegeleisen
2个回答

37

这两种合并方式的区别仅在于它们的提交历史不同(就像您展示的图表日志中一样)。

让我们通过图形来说明。 假设合并之前的提交历史如下:

A---B---C---D  master
     \
      E---F---G  develop

合并提交(多个父提交):

使用的命令是git merge branchname。这是将两个分支合并的默认方法。

当你在 SmartGit 中通过合并提交git merge develop)将develop分支合并到master分支时,提交历史记录将会变成:

A---B---C---D---M  master
     \         /
      E---F---G    develop

简单提交(一个父节点,“压缩”):

使用--squash选项合并两个分支,命令为git merge branchname --squash

--squash

生成工作树和索引状态,就像真正的合并发生了一样(除了合并信息),但实际上不会进行提交、移动HEAD 或记录$GIT_DIR/MERGE_HEAD(以使下一个git commit命令创建合并提交)。这允许您在当前分支之上创建一个单独的提交,其效果与合并另一个分支相同(或在八爪鱼情况下更多)。

当您在SmartGit中使用简单提交git merge develop --squash)将develop分支合并到master分支时,它会将来自develop分支的更改作为新的普通提交(就像真正的合并发生了一样)带入到master分支,并且提交历史将如下所示:

A---B---C---D---M  master
     \                 
      E---F---G    develop

1
仅作为@Marina的出色回答的补充,在某些集成(在我的情况下是GitLab)中,如果将-squash提交到父分支,则内部合并请求系统无法检测到已合并的分支。因此,一方面您拥有更清晰的历史记录,但是合并来源的检测会稍微困难一些。 - Tomas
2
我认为需要发出一个警告:压缩提交会丢失历史记录!如果你合并,git将知道导致功能集成的所有中间步骤,而git bisect将能够将任何回归定位到这些中间步骤之一。如果你压缩,你的功能分支对于git来说就变成了一个黑匣子,git bisect只能指出包含整个功能开发的一个压缩提交。最好全心全意地拥抱git的DAG历史模型,这将在未来为你节省许多麻烦。 - cmaster - reinstate monica

1

合并提交只是普通的提交(commit),但不同之处在于它们具有多个父级。 正如您所知,提交可能有也可能没有父提交,实际上合并提交是具有多个父提交(parent commit)提交(commit)


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