谁能告诉我这两个命令有什么区别:
git merge --squash
和
git merge --no-ff
我认为你的问题表明有点误解。--no-ff
并且--squash
不是对立的,而是微妙地不同的操作。阅读时请记住这一点。
合并的帮助页面说明以下内容--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'
如果你有这棵树,在 master 分支上并运行git merge
,Git 将执行所谓的“快进”合并。由于这两个历史之间没有分歧,Git 可以将master
分支移动到其所在的位置,topic
而无需做任何有趣的事情。它看起来像这样:
A --> B --> C --> D --> E
|
'topic'
'master'
topic 和 master 都指向同一个分支。现在,一些工作流程规则要求您在每次合并回master
. 这样可以保留分支的历史。无论哪种方式,您都会就应该如何完成而争论不休,但我不会在这里讨论这些。
如果你git merge --no-ff
在同一棵树上使用,它会强制 git 创建一个合并提交,给你一个像这样的树:
'master'
|
A --> B -------------> F
\ /
C --> D --> E
|
'topic'
F
新的合并提交--no-ff
强制 Git在哪里创建。