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

Edw*_*son 17 git merge squash

git branch --merged 似乎没有--squash很好地发挥.

如果你正常git merge,那么git branch --merged告诉你合并了哪些分支.但是,如果使用--squash选项,即使生成的树相同,也不是这种情况.

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

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

tor*_*rek 18

你不能从这里到达那里(正如指示说话的人).更确切地说,它没有意义.

问题是git merge --squash实际上并没有进行合并.假设您的分支历史记录如下所示(带分支topicdevel):

          H ? I ? J     <-- topic
        ?
? F ? G
        ?
          K ? L         <-- devel
Run Code Online (Sandbox Code Playgroud)

如果您签出devel并合并,topic您将获得M包含合并结果的新合并提交,并且M有两个父项:

          H ? I ? J     <-- topic
        ?         ?
? F ? G           ?
        ?         ?
          K ? L ? M     <-- devel
Run Code Online (Sandbox Code Playgroud)

但是如果你使用的git merge --squash topic话,你会得到一个新的提交(让我们用它标记S壁球):

          H ? I ? J     <-- topic
        ?
? F ? G
        ?
          K ? L ? S     <-- devel
Run Code Online (Sandbox Code Playgroud)

其中(正如您已经注意到的)提交的内容(树)S使得所有文件与提交时的文件相同M.但是从S到没有反向链接(父箭头)topic.它根本不是一个合并,它只是将所有的变化topic,压缩成一个单一的变化,并将其作为一个完全独立的提交添加.

现在,另一件事git merge --squash是它没有进行最后的提交.因此,您可以创建.gitgit将在"常规"合并上执行的文件,并执行具有您将在"真正"合并上获得的两个父级的提交.然后你会得到...正是你会得到什么,如果你运行git merge topic,提交(它贴上标签S或者M,它并不重要),其又具有相同的树,但是现在有两个家长箭头,指向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.

  • 很好的答案,谢谢你的解释.我认为git能够压缩提交并仍然执行三向合并,哦.我觉得`git merge --squash`有点误导; 我会选择专门的`git squash`. (3认同)