Git merge允许我们执行快进和没有快速快进分支合并。有什么想法何时使用快进合并以及何时不使用快进合并?
答案 0 :(得分:231)
当您想要清楚地了解功能分支时,--no-ff
选项很有用。因此,即使在此期间没有提交任何提交,FF也是可能的 - 您仍然希望有时让主线中的每个提交对应一个功能。因此,您将具有一堆提交的功能分支视为一个单元,并将它们合并为一个单元。从您的历史中可以清楚地看到,您使用--no-ff
进行分支合并。
如果你不关心这样的事情 - 你可能会尽可能地逃脱FF。因此,您将拥有更多类似svn的工作流感。
例如,此article的作者认为--no-ff
选项应该是默认选项,并且他的推理与我上面概述的相似:
考虑一下“功能”分支上的一系列次要提交共同构成一个新功能的情况:如果你只是在没有--no-ff
的情况下执行“git merge feature_branch”,那么就无法从Git中看到历史记录中哪些提交对象一起实现了一个功能 - 您必须手动读取所有日志消息。恢复整个功能(即一组提交),真是令人头痛[如果未使用--no-ff
] ,如果使用--no-ff
标志很容易做到[因为它只是一次提交]。“
答案 1 :(得分:5)
我可以举一个项目中常见的例子。
此处,选项--no-ff
(即true merge)会创建一个包含多个父级的新提交,并提供更好的历史记录跟踪。否则,--ff
(即fast-forward merge)默认为。
$ git checkout master
$ git checkout -b newFeature
$ ...
$ git commit -m 'work from day 1'
$ ...
$ git commit -m 'work from day 2'
$ ...
$ git commit -m 'finish the feature'
$ git checkout master
$ git merge --no-ff newFeature -m 'add new feature'
$ git log
// something like below
commit 'add new feature' // => commit created at merge with proper message
commit 'finish the feature'
commit 'work from day 2'
commit 'work from day 1'
$ gitk // => see details with graph
$ git checkout -b anotherFeature // => create a new branch (*)
$ ...
$ git commit -m 'work from day 3'
$ ...
$ git commit -m 'work from day 4'
$ ...
$ git commit -m 'finish another feature'
$ git checkout master
$ git merge anotherFeature // --ff is by default, message will be ignored
$ git log
// something like below
commit 'work from day 4'
commit 'work from day 3'
commit 'add new feature'
commit 'finish the feature'
commit ...
$ gitk // => see details with graph
(*)请注意,如果重新使用newFeature
分支,而不是创建新分支,git无论如何都必须进行--no-ff
合并。这意味着快进合并并不总是合格。
答案 2 :(得分:1)
当我们在开发环境中工作并将代码合并到暂存/生产分支时,那么Git没有更好的选择。通常,当我们在开发分支中为单个功能工作时,我们往往会有多个提交。以后跟踪具有多个提交的更改可能很不方便。如果我们使用Git与暂存/生产分支合并,而没有快进,那么它将只有1次提交。现在,无论何时我们想要还原功能,只需还原该提交即可。生活很轻松。
答案 3 :(得分:0)
也可能想要拥有个性化的功能分支,其中代码只是在一天结束时放置。这样可以更精细地跟踪开发。
我不想用非工作代码污染主开发,因此做--no-ff可能就是人们正在寻找的东西。
作为旁注,可能没有必要在个性化分支上提交工作代码,因为历史记录可以重写git rebase -i
并强制在服务器上,只要没有其他人在同一分支上工作。< / p>
答案 4 :(得分:0)
以下是具有差异的 git log 可视化。这些树看起来像从 dev 创建三个分支,称为 1 2 3,然后合并有和没有快进。我会把设置代码放在底部。可以在终端粘贴一段命令,快速设置和重置不同的git场景,对学习git很有帮助。
请注意,使用快进时,git 甚至不表示合并。
--no-ff --ff (default)
* Merge 3
| * 3
* | Merge 2 * Merge 3
| | * 2 | * 3
| |/ * | Merge 2
* / Merge 1 | | * 2
|/ | |/
| * 1 * / 1
|/ |/
* main * main
值得将这种方法与变基进行比较。
您可以重复运行它,它会删除并重新初始化存储库。它适用于 Windows,所以我认为如果你使用 *nix,你只需要更改文件路径和 rd
删除目录命令。
要查看快进的行为,请从最后的合并命令中删除 --no-ff
。如果您想查看提交 ID,请删除 --pretty
部分。
cd \user\docs\code\learning\github\sandbox
rd /s /q 0.git 1 2 3
git init --bare 0.git
git clone 0.git 1
cd 1
git config user.name "user"
git config user.email "user@email.com"
git commit --allow-empty -m main
git switch -c 1 main
git commit --allow-empty -m 1
git switch -c 2 main
git commit --allow-empty -m 2
git switch -c 3 main
git commit --allow-empty -m 3
git switch main
git merge --no-ff 1
git merge --no-ff 2
git merge --no-ff 3
git log --graph --oneline --first-parent --all --pretty=%s
答案 5 :(得分:0)
除了已发布的使用 --no-ff 的原因之外,在目标分支中保持正确的父顺序是另一个原因。
使用--no-ff,您上次提交中的父顺序将独立于您正在合并的分支的最后一次提交中的父顺序,其第一个父将是您所在的分支。如果您执行 ff,具有相同父级的提交将被合并到目标分支中,因此您在分支中最后一次提交的第一个父级将指向主线之外的提交。这可能不是您想要的。
例如,您可以使用 --first-parent 过滤分支历史记录以仅查看分支的主要更改,或默认使用第一个父级的其他操作,例如 revert
。如果您的分支没有保留正确的父引用,结果将与预期不同。