Git在合并时创建额外的分支

时间:2016-11-03 10:26:50

标签: git version-control merge gitlab

我的gitlab中有两个git分支R1609和R1609_dpl。

每当我向R1609推送内容时,我想使用触发器将这些更改合并到R1609_dpl中。 由于某种原因,git只为合并提交创建了一个额外的分支。合并后,提交历史记录如下所示:

Network

提交“将URL的X分支合并到X”似乎完全没必要。 我的合并代码:

git checkout R1609
git pull origin R1609
git checkout R1609_dpl
git pull origin R1609_dpl
git merge --no-ff R1609
git commit --amend -m "Push to R1609 triggered: Merge R1609 into R1609_dpl"
git push origin R1609_dpl

我错过了什么?我想摆脱额外的分支,只需合并到R1609_dpl分支,而无需进行两次合并提交。

提前致谢!

编辑: 摆脱了

git commit --amend -m "Push to R1609 triggered: Merge R1609 into R1609_dpl"

并添加了一个rebase但仍然没有运气

git checkout R1609
git pull origin R1609
git checkout R1609_dpl
git pull origin R1609_dpl
git merge --no-ff R1609
#Added rebase
git pull --rebase origin R1609_dpl
git push origin R1609_dpl

2 个答案:

答案 0 :(得分:1)

请注意git pull 表示 git merge

嗯,这意味着"首先运行git fetch,然后运行git merge,除非我告诉您作为第二步运行git rebase。"

因此,你有四个项目,我们可能会回到"潜在的"部分在一分钟创建合并:

  1. git checkout R1609; git pull origin R1609:这可能会在您当前(即R1609)分支上创建一个新的合并提交,使用它找到的任何内容并从您的上游获取,即其他(来源' s)Git' R1609

  2. git checkout R1609_dpl; git pull origin R1609_dpl。与步骤1一样,这可能会创建新的合并提交。

  3. git merge --no-ff R1609:此肯定会创建合并提交,除非它什么都不做。 (由于这里的第4项,最好不要做任何事。)

  4. git commit --amend -m "Push to R1609 triggered: Merge R1609 into R1609_dpl":这个"修改"使用新的不同消息将当前提交复制到新提交。它将目前的承诺推到一边。假设我们在第3步中进行了合并,这会将合并推到一边并用新的合并替换它。由于当前分支(现在为git log)指向新副本并且只有其reflog指向原始副本,因此推出的合并将从R1609_dpl输出消失。修改完成。

  5. 在某些方面,有点令人惊讶的是,您没有获得三次提交。您 获取的那个来自第1步,因为日志显示其消息为"合并分支' R1609' of< url>进入R1609"。所以现在是时候描述"潜在的"的事情。

    git fetch有两种可能,第二种可能分为两种情况:

    • 您的Git呼叫origin/R1609的上游,但他们(来源)Git只是呼叫R1609,与您自己的R1609同步,或者是背后:你有一些他们缺乏​​的提交(直到你推它们)。在这种情况下,git fetch不执行任何操作,并且没有任何内容可以合并,git merge什么都不做。 (是的,但也是嘘,为什么我们甚至打扰?:-)嗯,当然要检查。)

    • 上游与您的R1609不同步。 Git从上游获取一些提交。这可能严格提前您自己R1609上的提交,或者可能是他们的R1609有您缺少的提交,而您的{ {1}}有一个他们缺乏的提交。 R1609步骤无需关心;它只是带来他们所拥有的任何提交,你不会。然后它会更新您的fetch以记住他们的新提交。 1

    当fetch 带来某些东西时,你现在可能完全落后于 - 你只需要赶上他们的origin/R1609 - 或者你可能同时领先。在前一种情况下,R1609默认执行"快进"操作。 2 Git更改您的分支标签git merge,以便它指向与其R1609(您的R1609)相同的提交。当然,如果指定origin/R1609,Git会进行真正的合并。但是在后一种情况下,Git 必须进行真正的合并,以组合您的提交和它们的提交。所以你在这里得到一个合并,它的消息是--no-ff

    显然,上游的某些内容会导致新的提交出现在他们的 Merge branch 'R1609' of <url> into R1609上,Git发现它必须在上面的步骤1中合并。上游R1609没有任何事情发生,所以你的Git能够在步骤2中适当地快进或根本不做任何事情。步骤3创建一个新的合并,并且在创建第三个合并时将步骤4推到一边,留下两个可见的合并。

    (我看到,当我写完所有这些内容时,你已经找到了在R1609_dplR1609上引入提交的罪魁祸首。)

    1 好吧,只要您的Git是1.8.4或更新版本。较旧的Git版本有时无法更新远程跟踪分支。 (具体来说,他们故意不在origin脚本的fetch运行中更新它。结果证明这是一个错误,因此在1.8.4中进行了更改。)

    2 虽然pull文档将此描述为快进合并,但它根本不是合并。快进是标签移动的属性。给定一个指向提交X的标签,以及一个将其更改为指向标签Y的请求,我们测试:&#34; X是Y的祖先?&#34;如果是这样,这种变化是快速的。如果没有,那就没有了。

    git mergegit fetch都有内置代码来检测快进移动和非快进移动。这就是git pull标志的全部内容,在推送时 - 就此而言,在提取时,尽管对于获取它总是通过refspec中的--force语法来完成。如果没有+--force标志,Git拒绝将提交X中的分支标签更改为提交Y,除非提交X是Y的祖先。

    +命令当然也有相同的代码,并且会快进标签而不是合并,前提是(a)这是可能的,(b)你没有禁止它。由于此操作是在当前分支上完成的,因此使用当前索引和工作树,merge还会更新索引和工作树以进行匹配。 fetch和push代码既不更新索引也不更新工作树。

答案 1 :(得分:0)

据我所知,没有“额外”分支。你所看到的仅仅是对Git中实际发生的事情的图形解释。下面是一个显示合并过程的前两个步骤的图表:

R1609:     _____
R1609_dpl: _____\_______   (R1609_dpl after merge with R1609)

如果您只进行了简单的合并,而不修改提交,那么您的图表应该与我上面的内容类似。也就是说,您可以看到R1609在某个时刻进入R1609-dpl

但是,您执行了以下额外步骤:

git commit --amend -m "Push to R1609 triggered: Merge R1609 into R1609_dpl"

修改了(读取:重写)合并提交。这意味着原始合并提交不再是R1609_dpl分支的一部分。我的预感是你的图形工具试图通过单独的棕色线来显示它。您会注意到这个“分支”(它不是真正的分支)似乎只有一个提交。此提交是您的原始合并提交。