0

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

br1  br2
  A
    \ 
     B
     C
     D

现在,当我做

git checkout br1
git merge --no-ff br2

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

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

好的..现在,奇怪的是;现在我称之为“git status”;它说我在远程分支之前提交了 4 次。这是怎么回事?我不应该只有一个承诺吗?

奇怪的是,当我从 Stash(基本上是 Git Web UI)检查时,它确认了这个“4 次提交”状态,我在“br1”和“br2”下都看到了相同的提交(BC 和 D)...... .

我假设当我使用“--no-ff”参数时,“br2”(BCD)的提交不会被复制到“br1”,只会创建合并提交。我在这里弄错了吗?

4

3 回答 3

3

更新:我写完这个答案后,发帖人改变了问题。此更新回答了其余答案未涵盖的问题之一。

好的..现在,奇怪的是;现在我称之为“git status”;它说我在远程分支之前提交了 4 次。这是怎么回事?我不应该只有一个承诺吗?

在合并 ( --no-ff) 提交ADintoE之后,本地分支比远程分支早 4 次提交(我想远程分支仍然指向A)。这是对的。

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

Drequires C(其父级) that requires Bthat requires AA远程服务器上已经存在,链到此结束。B, C,D并且E在远程服务器上不存在。必须全部推送,以保持远程服务器上数据的一致性。


其余的回复处理了定义不是很明确的原始问题。海报提到git log --graph和(可能)Atlassian Stash。这两个工具(以及git我知道的所有其他界面)都首先在提交历史中显示最近的提交。这个答案使用相同的约定。

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

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

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


无论如何,git merge --no-ff是在不同的情况下使用的。

假设我们有这张图:

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

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

在这种情况下,命令:

git checkout br1
git merge br2

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

这是图表的样子:

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

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

这里就派上用场--no-ff了。如果您希望此合并创建包含由 commits 引入的所有更改的合并提交,D然后C运行B

git checkout br1
git merge --no-ff br2

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

 A <-- br1
 |\
 | B <-- br2
 | |
 | C
 | |
 | D
 |/
 E
 |
...
于 2016-02-26T09:45:50.030 回答
2

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

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

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

您的本地br1是对 的引用E,而您的远程br1仍然是对 的引用A。因此,有四个提交BC和)对.DEbr1

于 2016-02-26T09:40:22.157 回答
1

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

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

于 2016-02-26T09:22:54.083 回答