为什么git merge有时候会创建一个commit,有时候不会?

ijxebb2r  于 2023-05-12  发布在  Git
关注(0)|答案(5)|浏览(648)

当我从另一个分支到当前工作区执行git merge时,git有时会进行一次新的提交:

Merge remote-tracking branch xxx into xxx

有时,它并不:

Fast-forward
... src files ...

那么,是什么决定了一个提交是否应该被创建?

apeeds0o

apeeds0o1#

所谓的“快进”合并不会产生提交,而其他合并(通常被称为“octopus merge”(现在你明白为什么github的mascott是octocat了))会产生提交。
基本上,当你的分支没有分叉时,就会发生快进。
假设你想将一个分支foo合并到master分支中。如果这些分支没有分叉,你会有一个这样的历史(每个*代表一次提交):

*---* (master)
     \
      *---*---* (foo)

在这种情况下,合并是快进,因为(根据图论,这是git图的底层基础),master可以从foo到达。换句话说,您只需将master引用移动到foo,就完成了:

*---*
     \
      *---*---* (master, foo)

当你的分支分叉时:

*---*---* (master)
     \
      *---*---* (foo)

你必须创建一个commit来“join”这两个分支:

↓
*---*---*-------* (master)
     \         / 
      *---*---* (foo)

箭头所指的提交是合并提交,它有两个父提交(前一个master分支提示,当前foo分支提示)。
请注意,您可以使用--no-ff选项强制Git为快进合并创建一个合并提交。
我强烈推荐阅读http://think-like-a-git.net/,以更好地理解图论如何应用于git(你不需要知道图论,你需要知道的一切都在网站上),这将使使用Git变得非常容易:)

qncylg1j

qncylg1j2#

您可以使用--no-ff选项强制执行新的提交,以避免快进。

nbysray5

nbysray53#

快进意味着一个提交已经发生并存储在你的日志中,你的HEAD(指针)已经向前移动到那个提交。您可以检出合并行为here

ebdffaop

ebdffaop4#

当没有提供--no-ff选项时,如果你正在合并的分支的头部是被合并分支的祖先,git将不会创建提交。在这种情况下(没有--no-ff选项),它只会移动头部(这是一个快进)。

weylhg0b

weylhg0b5#

以下是documentation

快进合并

通常当前分支头是命名提交的祖先。这是最常见的情况,尤其是当从git pull调用时:您正在跟踪上游存储库,没有提交任何本地更改,现在希望更新到更新的上游修订版。在这种情况下,不需要新的提交来存储组合的历史;相反,HEAD(沿着索引)被更新为指向命名提交,而不创建额外的合并提交。
可以使用--no-ff选项抑制此行为。

真合并

除了在快速合并中(见上文),要合并的分支必须通过合并提交绑定在一起,合并提交将它们都作为其父分支。
提交一个合并版本,协调所有要合并的分支的更改,并将HEAD、索引和工作树更新到该版本。只要它们不重叠,就可以在工作树中进行修改;更新将保留它们。
当不清楚如何协调更改时,会发生以下情况:
HEAD指针保持不变。
MERGE_HEAD引用被设置为指向另一个分支头。
合并干净的路径将在索引文件和工作树中更新。
对于冲突路径,索引文件最多记录三个版本:stage 1存储来自共同祖先的版本,stage 2存储来自HEAD的版本,stage 3存储来自MERGE_HEAD的版本(您可以使用git ls-files -u检查这些stage)。工作树文件包含“合并”程序的结果;即具有熟悉的冲突标记的3路合并结果。
未进行其他更改。特别是,在开始合并之前进行的本地修改将保持不变,它们的索引条目也保持不变,即匹配HEAD。
如果你尝试了一个合并,导致了复杂的冲突,并希望重新开始,你可以使用git merge --abort恢复。

相关问题