Git branch --merged / --no-merged和--squash选项

时间:2013-10-11 01:19:23

标签: git merge squash

git branch --merged似乎与--squash没有很好的配合。

如果您执行正常git merge,则git branch --merged会告诉您哪些分支已合并。但是,如果使用--squash选项,则情况并非如此,即使结果树是相同的。

我怀疑这是一个git缺陷,想知道是否有一些git-fu我错过了,或者我是否误解了一些东西。

简而言之:我想使用--squash,但也希望git告诉我,我压扁的另一个分支是否已经过了。

1 个答案:

答案 0 :(得分:15)

你不能从这里到达那里(正如发表指示的同事所说)。更准确地说,它没有意义。

问题是git merge --squash实际上并没有进行合并。例如,假设您的分支历史记录是这样的(使用分支topicdevel):

          H ⬅ I ⬅ J     <-- topic
        ⬋
⬅ F ⬅ G
        ⬉
          K ⬅ L         <-- devel

如果你签出devel并合并topic,你会得到一个包含合并结果的新合并提交M,而M有两个父母:

          H ⬅ I ⬅ J     <-- topic
        ⬋         ⬆
⬅ F ⬅ G           ⬆
        ⬉         ⬆
          K ⬅ L ⬅ M     <-- devel

但是如果你使用git merge --squash topic,你会得到一个新的提交(让它标记为S用于压缩):

          H ⬅ I ⬅ J     <-- topic
        ⬋
⬅ F ⬅ G
        ⬉
          K ⬅ L ⬅ S     <-- devel

其中(如您所述)提交S内容(树)使得所有文件与提交M中的文件相同。但是没有从S到topic的反向链接(父箭头)。它根本不是合并,它只是从topic获取所有更改,将它们压缩为单个更改,并将其添加为完全独立的提交。

现在,关于git merge --squash的另一件事是它没有进行最后的提交。因此,您可以创建git将在“常规”合并上创建的.git文件,并执行具有您将在“真正”合并上获得的两个父级的提交。然后你会得到......如果你运行git merge topic,提交(标记为SM,无关紧要)再次拥有相同的树,你会得到... ,但现在有两个父箭头,指向LJ,就像M一样。

实际上,运行git merge --squash与运行git merge --no-commit几乎完全相同,但合并完成后留下的跟踪文件除外(git commit使用其中一些设置父母)。 squash版本不会写入.git/MERGE.git/MERGE_HEAD.git/MERGE_MODE。 (它确实创建.git/MERGE_MSG,与git merge --no-commit相同,并且还会创建.git/SQUASH_MSG。)

因此,基本上,您可以选择:真正的合并(最终提交中的两个或更多个父项),或者壁球(相同的树组合机制,但最终提交中只有一个父项)。并且,由于git branch --merged通过查看存储库中存储的每个提交的“父箭头”来工作,因此只有真正的合并才是合并,因此git branch之后只能发现真正的合并。