Git Merge --no-ff 会复制提交



我今天有一个奇怪的git行为,我想问一下这是否正常。现在,情况是这样的(新的提交被添加到底部):

br1  br2
  A
     
     B
     C
     D

现在,当我制作

git checkout br1
git merge --no-ff br2

它变成这样(请从上到下阅读;最新的提交是"E")

br1  br2
  A
  |  
  |  B
  |  C
  |  D
  | /
  E

还行。。现在,奇怪的是;现在我称之为"git 状态";它说我在远程分支之前提交 4 次。这是怎么回事?难道我不应该只做一个承诺吗?

奇怪的是,当我从 Stash(基本上是 Git Web UI)检查时,它确认了这个"4 个提交"状态,并且我在"br1"和"br2"下看到了相同的提交(B C 和 D)两个......

我假设当我使用"--no-ff"参数时,"br2"(B C D)的提交不会被复制到"br1",而只会创建合并提交。我弄错了吗?

更新:在我写完这个答案后,海报改变了问题。此更新回答了答案其余部分未涵盖的问题之一。

还行。。现在,奇怪的是;现在我称之为"git 状态";它说我在远程分支之前提交 4 次。这是怎么回事?难道我不应该只做一个承诺吗?

将提交合并(--no-ff)后AD E,本地分支比远程分支早 4 次提交(我想远程分支仍然指向 A)。这是正确的。

让我们计算一下本地分支(现在指向 E)和不在远程分支(指向 A)上的提交。 E显然是其中之一。 E 作为合并提交,有两个父级:A(存在于远程分支上)和D(不存在于远程分支上)。当gitE推送到远程服务器时,它需要推送其父级(否则E在远程服务器上无效)。

D需要需要B C(其父级)需要AA已经存在于远程服务器上,链到此结束。 远程服务器上不存在BCDE。必须推送所有这些数据,以保持远程服务器上数据的一致性。


答复的其余部分处理了定义不是很明确的原始问题。海报提到了git log --graph和(可能)Atlassian Stash。这两个工具(以及我知道的所有其他git接口)都首先呈现提交历史记录中的最新提交。此答案使用相同的约定。

git merge --no-ff在您描述的情况下没有任何影响。

br1作为当前分支,git merge br2 br1提交引入的更改,这些更改可从br2访问,而无法从br1访问。根据br1br2上的相对位置,git merge可以创建一个新的提交(其中包含从br1无法访问的提交引入的所有更改),或者它可以只是将br1分支头移动到新位置(并且不创建任何新提交)。

在您的情况下,br2 落后于 br1 1 次提交,并且由于A是合并提交,因此也可以从 br1 访问从 br2 访问的所有提交。


无论如何,git merge --no-ff用于不同情况。

假设我们有这个图:

 B <-- br2
 |
 C
 |
 D
 |
 E <-- br1
 |
...

分支br2是从分支br1创建的(当时两者都在提交E),然后br2被签出并添加了三个新的提交(DCB)。

在此情况下,命令:

git checkout br1
git merge br2

不要创建新分支。分支br1被移动到提交Bbr2所在的位置),仅此而已。现在,可以从br2访问的所有提交也可以从br1访问。 br2成功合并为br1

这是图形的外观:

br1 --> B <-- br2
        |
        C
        |
        D
        |
        E
        |
       ...

这种合并称为fast-forward,因为分支br1从其先前的位置"快进"移动到新位置(可能与一次从E移动到B一次提交分支b2相反)。只有当br2br1的唯一子路径时,才有可能(从E开始,每个提交都有一个子提交,路径到达B)。

--no-ff就在这里发挥作用了。如果您希望此合并创建一个合并提交,其中包含提交DCB 引入的所有更改,请运行:

git checkout br1
git merge --no-ff br2

--no-ff选项的存在禁止分支b1的快速转发,并强制创建新的合并提交。图形将如下所示:

 A <-- br1
 |
 | B <-- br2
 | |
 | C
 | |
 | D
 |/
 E
 |
...

我认为你误解了分支在 Git 中的工作方式。分支是轻量级的,这意味着当您创建新分支或将一个分支合并到另一个分支时,不会复制任何内容。

分支是指向提交的引用。由于每个提交都链接到其以前的提交,因此当您指向一个提交时,您实际上是指向该提交的历史记录

在您的示例中,E是一个合并提交,它将两个分支组合在一起,从而创建单个历史记录。这意味着在将br2合并到br1后,br1现在是E的引用)将了解br2的历史(仍然是D的引用),因为DCBE历史的一部分。

您的本地br1是对E的引用,而您的远程br1仍然是对A的引用。因此,有四个提交(BCDE)是br1历史的新提交。

从技术上讲,这 4 个提交实际上是 br1 的一部分。如果删除br2,提交仍将是br1的一部分。当您重置合并提交时,差异就出现了。如果您进行硬重置,您将在合并提交之前返回提交,即 E .当您想要回滚时,这尤其有用。所以是的,你领先四次提交,但只要你不重置br1,你应该没问题。

另外-no-ff不要阻止 git 复制提交。这是为了使提交与br1树分开。这样,您就可以维护分支的历史记录和提交上下文,而不是与不同功能相关的大量提交

相关内容

  • 没有找到相关文章

最新更新