有人可以告诉我这两个命令之间有什么区别:
git merge --squash
和
git merge --no-ff
答案 0 :(得分:6)
我认为你的问题表明有点误会。 --no-ff
和--squash
不是对立的,而是略有不同的操作。在阅读时请记住这一点。
help page for merge说明以下关于--squash
:
--squash
和--no-squash
生成工作树和索引状态,就像发生了真正的合并一样(合并信息除外),但实际上并没有 提交或移动HEAD,也不记录$ GIT_DIR / MERGE_HEAD 导致下一个git commit命令创建合并提交。这个 允许您在当前分支之上创建单个提交 其效果与合并另一个分支相同(或者更多 章鱼)。
使用--no-squash执行合并并提交结果。这个选项 可以用来覆盖--squash。
这有点令人困惑,需要一些关于git
内部的知识。首先,我们需要了解常规提交和合并提交之间的区别。常规提交有一个父级,并且只是一个应用于它之前的提交的变更集:
A --> B --> C
合并提交有多个父级,它在树中的一个位置,您将两个或多个谱系放在一起:
A --> B --> F
/
C --> D - /
了解A
,B
,C
和D
是如何进行常规提交,但F
是合并提交,因为它有多个父级( B
和D
)?这就是git merge --no-ff
会产生的。它迫使Git创建一个合并提交,将两个历史结合在一起。
git merge --squash
会做一些不同的事情。它会阻止Git创建合并提交,但仍然会引入所做的更改C
和D
,因此您的树看起来像这样:
A --> B --> F'
C --> D
F'
包含所做的更改C
和D
,但没有迹象表明您在存储库中合并了两棵树。
--no-ff
是一个稍微不同的操作。它迫使Git创建合并提交,即使它不是真的有必要。作为参考,这里有关于--no-ff
及其相对--ff-only
的手册所说的内容:
--no-ff
即使合并解析为快进,也要创建合并提交。
--ff-only
拒绝以非零状态合并和退出,除非当前HEAD已经是最新的,或者合并可以解析为 快进。
要理解,最好看一个例子:
A --> B --> C --> D --> E
| |
'master' 'topic'
如果你有这棵树,在主分支上,然后运行git merge
,Git会执行所谓的"快进"合并。由于两个历史之间没有分歧,Git可以将master
分支移动到topic
所在的位置而不做任何有趣的事情。它看起来像这样:
A --> B --> C --> D --> E
|
'topic'
'master'
主题和主人都指向同一个分支。现在,某些工作流程规则要求您在每次合并回master
时创建合并提交。这保留了分支的历史。你可以在任何方面得到论证,但我不会在这里进入。
如果你在同一棵树上使用git merge --no-ff
,它会强制git创建一个合并提交,给你一棵这样的树:
'master'
|
A --> B -------------> F
\ /
C --> D --> E
|
'topic'
F
是新的合并提交--no-ff
迫使Git创建。