Git分支 - 合并/ - 没有合并和--squash选项 [英] Git branch --merged / --no-merged and --squash option

查看:245
本文介绍了Git分支 - 合并/ - 没有合并和--squash选项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

git branch --merged 似乎不会与--squash很好地搭配。

如果你做一个正常的 git merge ,那么 git branch --merged 告诉你哪些分支已被合并。但是,如果使用了--squash选项,即使生成的树是相同的,情况并非如此。



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

简而言之:我想使用--squash,但也想要git告诉我,我压扁到另一个分支的分支是否已经被淹没。

你不能从这里到达那里(正如指导者所说的那样)。更确切地说,它没有任何意义。



问题在于 git merge --squash 实际上并没有合并。假设您的分支历史记录如下所示(例如分支主题 devel ):

  H⬅I⬅J < -  topic 

⬅F⬅G

K⬅L < - devel

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

  H⬅I⬅J < -  - 话题

$ F $ G $

K $ L $ M $ - pre>

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

  H⬅I⬅J < - 话题

⬅F⬅G

K (如你已经注意到的)内容
提交 S 的所有文件(树)使得所有文件与提交时相同 M 。但是从S到 topic 没有反向链接(父箭头)。它根本不是合并,它只是从主题中进行所有更改,将它们压缩为单个更改,并将其作为完全独立的提交添加。



现在,关于 git merge --squash 的另一件事就是它不会进行最终的提交。因此,您可以创建git在常规合并时使用的 .git 文件,然后执行一次提交,以获得您在真正合并时获得的两个父代。然后你会得到......如果你运行 git merge topic ,一个提交(标签为 S M ,无关紧要),它又有相同的树,但现在有两个父箭头,指向 L J ,就像 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 branch --merged doesn't appear to play nicely with --squash.

If you do a normal git merge, then git branch --merged tells you which branches have been merged. This is not the case however if the --squash option is used, even though the resulting tree is the same.

I doubt this is a git defect and would like to know if there is some git-fu I'm missing, or if I have misunderstood something.

In short: I want to use --squash, but also want git to tell me if the branch I squashed into another one has been --merged.

解决方案

You can't get there from here (as the fellow giving directions said). More precisely, it does not make sense.

The problem is that git merge --squash does not actually do a merge. Suppose your branch history looks like this, for instance (with branches topic and devel):

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

If you check out devel and merge topic you get a new merge commit M that contains the result of the merge, and M has two parents:

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

But if you use git merge --squash topic you get, instead, a new commit (let's label it S for squash):

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

where (as you already noted) the contents (the tree) of commit S makes all the files come out the same as they would in commit M. But there's no back-link (parent arrow) from S to topic. It's not a merge at all, it's just taking all the changes from topic, squashing them into a single change, and adding that as an entirely independent commit.

Now, the other thing about git merge --squash is that it does not make the final commit. So you could create the .git files that git would on a "regular" merge, and do a commit that has the two parents you'd get on a "real" merge. And then you'd get ... exactly what you get if you run git merge topic, a commit (label it S or M, it does not matter) that has the same tree again, but now has two parent-arrows, pointing to L and J, just like M.

In fact, running git merge --squash is almost exactly the same as running git merge --no-commit, except for the tracing files left behind when the merge is done (git commit uses some of these to set up the parents). The squash version does not write to .git/MERGE, .git/MERGE_HEAD, and .git/MERGE_MODE. (It does create .git/MERGE_MSG, the same as git merge --no-commit, and it also creates .git/SQUASH_MSG.)

So, basically, you have your choice: a real merge (two or more parents on the final commit), or a squash (same tree-combining mechanisms, but only one parent on the final commit). And, since git branch --merged works by looking at the "parent arrows" of each commit stored in the repository, only a real merge is really a merge, so only a real merge can be discovered later by git branch.

这篇关于Git分支 - 合并/ - 没有合并和--squash选项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆