我的gitlab中有两个git分支R1609和R1609_dpl。
每当我向R1609推送内容时,我想使用触发器将这些更改合并到R1609_dpl中。 由于某种原因,git只为合并提交创建了一个额外的分支。合并后,提交历史记录如下所示:
提交“将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
答案 0 :(得分:1)
请注意git pull
表示 git merge
。
嗯,这意味着"首先运行git fetch
,然后运行git merge
,除非我告诉您作为第二步运行git rebase
。"
因此,你有四个项目,我们可能会回到"潜在的"部分在一分钟创建合并:
git checkout R1609; git pull origin R1609
:这可能会在您当前(即R1609
)分支上创建一个新的合并提交,使用它找到的任何内容并从您的上游获取,即其他(来源' s)Git' R1609
。
git checkout R1609_dpl; git pull origin R1609_dpl
。与步骤1一样,这可能会创建新的合并提交。
git merge --no-ff R1609
:此肯定会创建合并提交,除非它什么都不做。 (由于这里的第4项,最好不要做任何事。)
git commit --amend -m "Push to R1609 triggered: Merge R1609 into R1609_dpl"
:这个"修改"使用新的不同消息将当前提交复制到新提交。它将目前的承诺推到一边。假设我们在第3步中进行了合并,这会将合并推到一边并用新的合并替换它。由于当前分支(现在为git log
)指向新副本并且只有其reflog指向原始副本,因此推出的合并将从R1609_dpl
输出消失。修改完成。
在某些方面,有点令人惊讶的是,您没有获得三次提交。您 获取的那个来自第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_dpl
上R1609
上引入提交的罪魁祸首。)
1 好吧,只要您的Git是1.8.4或更新版本。较旧的Git版本有时无法更新远程跟踪分支。 (具体来说,他们故意不在origin
脚本的fetch
运行中更新它。结果证明这是一个错误,因此在1.8.4中进行了更改。)
2 虽然pull
文档将此描述为快进合并,但它根本不是合并。快进是标签移动的属性。给定一个指向提交X的标签,以及一个将其更改为指向标签Y的请求,我们测试:&#34; X是Y的祖先?&#34;如果是这样,这种变化是快速的。如果没有,那就没有了。
git merge
和git 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
分支的一部分。我的预感是你的图形工具试图通过单独的棕色线来显示它。您会注意到这个“分支”(它不是真正的分支)似乎只有一个提交。此提交是您的原始合并提交。