git branch --merged
似乎不能很好地与 --squash 配合使用。
如果您执行普通的 git merge
,那么 git branch --merged
会告诉您哪些分支已被 merge 。但是,如果使用 --squash 选项,则情况并非如此,即使生成的树是相同的。
我怀疑这是一个 git 缺陷,想知道我是否遗漏了一些 git-fu,或者我是否误解了什么。
简而言之:我想使用 --squash,但也希望 git 告诉我我压缩到另一个分支中的分支是否已被 --merged。
最佳答案
你不能从这里到达那里(正如指路的人所说)。更准确地说,它没有意义。
问题是 git merge --squash
实际上并没有进行 merge 。假设您的分支历史看起来像这样,例如(分支 topic
和 devel
):
H ⬅ I ⬅ J <-- topic
⬋
⬅ F ⬅ G
⬉
K ⬅ L <-- devel
如果你 checkout devel
并 merge topic
你会得到一个新的 merge 提交 M
包含 merge 的结果,并且 M
有两个 parent :
H ⬅ I ⬅ J <-- topic
⬋ ⬆
⬅ F ⬅ G ⬆
⬉ ⬆
K ⬅ L ⬅ M <-- devel
但是,如果您使用 git merge --squash topic
,您会得到一个新的提交(让我们将其标记为 S
表示 squash):
H ⬅ I ⬅ J <-- topic
⬋
⬅ F ⬅ G
⬉
K ⬅ L ⬅ S <-- devel
其中(正如您已经指出的那样)提交 S
的内容(树)使所有文件的输出与提交 M 中的相同
。但是没有从 S 到 topic
的反向链接(父箭头)。这根本不是 merge ,它只是从 topic
中获取所有更改,将它们压缩成一个更改,并将其添加为一个完全独立的提交。
现在,关于 git merge --squash
的另一件事是它不会进行最终提交。因此,您可以创建 .git
文件,git 将在“常规” merge 中执行此操作,并执行一个提交,其中包含您在“真实” merge 中获得的两个父项。然后你会得到...如果你运行 git merge topic
,你会得到什么,一个提交(标记为 S
或 M
,没关系)再次具有相同的树,但现在有两个父箭头,指向 L
和 J
,就像 M
.
事实上,运行 git merge --squash
几乎与运行 git merge --no-commit
完全相同,除了在 merge 完成(git commit
使用其中的一些来设置父级)。 squash
版本不会写入 .git/MERGE
、.git/MERGE_HEAD
和 .git/MERGE_MODE
. (它确实创建了 .git/MERGE_MSG
,与 git merge --no-commit
相同,它也创建了 .git/SQUASH_MSG
。 )
因此,基本上,您有自己的选择:真正的 merge (最终提交时有两个或更多父级),或挤压(相同的树组合机制,但最终提交时只有一个父级)。而且,由于 git branch --merged
通过查看存储在存储库中的每个提交的“父箭头”来工作,只有真正的 merge 才是真正的 merge ,所以只有真正的 merge 才能在以后被发现通过 git 分支
。
关于Git branch --merged/--no-merged 和 --squash 选项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19308790/