Git Merge --no-ff复制提交

时间:2016-02-26 09:08:27

标签: git merge fast-forward

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

br1  br2
  A
    \ 
     B
     C
     D

现在,当我做

git checkout br1
git merge --no-ff br2

它变成这样(至少是git log --graph告诉我的):

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

好的..现在,奇怪的是;现在我打电话给#34; git status&#34 ;;它说我在远程分支之前提交了4个提交。这是怎么回事?难道我不能只提前一次提交吗?

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

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

3 个答案:

答案 0 :(得分:2)

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

分支是指向到提交的引用。由于每个提交都与其先前的提交相关联,因此当您指向一个提交时,您实际上指向该提交的历史

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

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

答案 1 :(得分:2)

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

  

好的..现在,奇怪的是;现在我打电话给#34; git status&#34 ;;它说我在远程分支之前提交了4个提交。这是怎么回事?难道我不能只提前一次提交吗?

将提交--no-ffA合并到D之后,本地分支是远程分支之前的4次提交(我想远程分支)仍然指向E)。这是正确的。

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

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

其余的回复会对原始问题进行处理。该海报引用了E和(可能)Atlassian Stash。这两个工具(以及我所知道的所有其他git log --graph接口)都首先在提交历史记录中提供最新的提交。这个答案使用相同的约定。

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

git作为当前分支,br1git merge br2提交的更改引入br1,但br2无法访问这些更改。根据{{​​1}}关于br1的相对位置,br1可以创建一个新提交(包含由br2无法访问的提交所引入的所有更改)或者它可以只是将git merge分支头移动到新位置(并且不会创建任何新提交)。

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

无论如何,br2用于不同的情况。

我们假设我们有这张图:

br1

分支git merge --no-ff是从分支 B <-- br2 | C | D | E <-- br1 | ... 创建的(当时两者都在提交br2)然后检出br1并提交了三个新提交({{1} }},Ebr2)已添加。

在这种情况下,命令:

D

不要创建新分支。分支C被移动到提交B(其中git checkout br1 git merge br2 是)并且全部都是。现在,br1可以访问的所有提交也可以从B访问。 br2已成功合并到br2

这就是图表的样子:

br1

这种合并称为br2,因为分支br1已被移动&#34;快进&#34;从其先前的位置到新的位置(可能与分支br1 --> B <-- br2 | C | D | E | ... 相反,一次从fast-forward移动到br1一个提交。仅当b2E的唯一子路径时才有可能(从B开始,每个提交都有一个子提交,路径到达br2)。< / p>

这里有br1。如果您希望此合并创建包含提交EB--no-ff引入的所有更改的合并提交,那么您运行:

D

C选项的存在禁止快速转发分支B并强制创建新的合并提交。该图表如下所示:

git checkout br1
git merge --no-ff br2

答案 2 :(得分:1)

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

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