git-merge是否将“to-be-merged”分支中的文件添加到head或not

时间:2018-04-10 19:50:59

标签: git git-merge git-rebase

所以我和我的团队正在敏捷开发过程中开展一个项目。每次迭代都有test分支的几个分支。每个分支充当迭代的任务。迭代完成后,所有任务分支都合并到test分支中,test分支合并到master

我遇到的问题是将test合并到master。在这种特定情况下,master完全落后,test包含许多文件甚至不包含在master中。因此,当我通过拉取请求比较testmaster时,其行为就像test中的所有新文件都不会添加到master

这是git-merge的工作原理吗?它只更新master中更改的文件而不关心添加的文件?

这是我做git-rebase的唯一选择吗?如果是这样,那怎么办?

编辑:我可能已找到问题的根源。如果某些任务分支在迭代开始时从master分支出来,然后在最后合并到test,该怎么办?将test合并到master时会导致一些问题吗?每当我在Github上查看我的test分支时,它会说:“这个分支是7个提交,5个提交在主人之后”。

2 个答案:

答案 0 :(得分:1)

根据您的编辑,我们将其分为两部分。

首先,您直接询问git操作应该如何表现:

  

这是git-merge的工作原理吗?它只更新master中已更改的文件,并不关心添加的文件?

没有;合并时应包含远程分支上的任何更改 - 包括添加新文件。如果没有发生这种情况,还会发生其他事情。

  

这是我做git-rebase的唯一选择吗?

基于边缘情况的几个例外,您应该期望结果内容(TREE)对于rebase与合并相同。无论是什么使得合并不按预期执行,可能导致rebase以意想不到的方式运行。

拒绝或合并的选择(理论上)只是关于如何保留历史。

第二:好的......那么这里到底发生了什么?

很难说完全正在发生什么,因为很难获得有关回购当前状态的足够信息。但我可以制定一些场景,并谈谈合并是如何工作的,也许这会让你足够继续,你可以解决它... ...

假设你发起这样的合并:

git checkout branchA
git merge branchB

现在git将确定三个提交:

  • 我们的 - 签出的提交(即branchA指向的内容)
  • 他们的 - 其历史正在合并的提交(即branchB`指向的提交)
  • base - "合并基地"在我们的他们的之间。通常,这可以概括为" 我们的最新共同祖先和他们的"

所以,如果你有

A -- B -- C -- D -- O <--(branchA)
      \
       E -- F -- T <--(branchB)

然后O我们的T他们的B base

下一个git会在BT之间计算一个补丁(大致差异) - 我们可以调用它们#34;他们的变化&#34; - 以及BO之间的补丁 - 我们可以致电&#34;我们的更改&#34;。

如果提交E添加了以前不存在的文件foo.txt,那么我们的更改中不会对该文件进行任何更改(因为它在B中都不存在或O),但foo.txt将在其更改中成为新文件(因为它在B中不存在但在T中确实存在。)< / p>

现在git想要创建一个包含我们的更改及其更改的组合补丁。如果我们的更改及其更改都尝试修改相同的代码块,则可能会出现冲突。但在我们的&#34;新文件&#34;因为我们的更改没有提及foo.txt,所以不会发生冲突。合并后的补丁应包含&#34;新文件foo.txt&#34;使用T上显示的文件内容。

所以大部分时间,如果merge表现得很混乱,你可以通过了解用作合并基础的内容来开始理解它。

git merge-base branchA branchB

将打印出提交ID。问题是,提交是否包含foo.txt?如果确实如此,那么你就不会得到你期望的行为;然后将问题简化为&#34;找出计算出的合并库包含foo.txt的原因。

现在在上面的示例中,此命令将返回B的ID,该ID不包含foo.txt。那么为什么你的情况会有所不同呢?

在编辑中,您描述了一些分支是从master创建的并合并到测试中。这不一定是个问题。说我们有

A -- B <--(master)

你说

git checkout master
git branch test

然后在test上进行了一些工作。

A -- B <--(master)
      \
       C -- D <--(test)

现在有人创建了一个任务分支,但他们是从master创建的。

A -- B <--(master)
     |\
     | E -- F <--(task1)
      \
       C -- D <--(test)

然后他们将task合并到test

A -- B <--(master)
     |\
     | E ----- F <--(task1)
      \         \
       C -- D -- T <--(test)

其他一些影响正在影响master

A -- B -- G -- H -- O <--(master)
     |\
     | E ----- F <--(task1)
      \         \
       C -- D -- T <--(test)

现在,在这种情况下,task1创建了master&#34;来自git&#34;无所谓。事实上,master甚至中当前存储的内容都反映了它是从test创建的事实。它也可以在提交C之前从task1创建。

意味着合并仍然可以正常工作。

但这是一个不同的场景......如果从master创建master的人在意识到他们需要分支之前实际提交了更改A -- B <--(master) \ C -- D <--(test) 该怎么办?所以在这种情况下,我们再次从

开始
task1

并且开发人员开始在master上编码A -- B -- E <--(master) \ C -- D <--(test) 。他们承诺,而你啊

master

然后有人说&#34;嘿,老兄,你不能直接在git checkout master git checkout -b task1 # work continues on the task1 branch git commit &#34;上工作,所以我们试着解决问题。

master

其他一些工作发生在A -- B -- E -- G <--(master) \ \ \ F <--(task1) \ C -- D <--(test) 上,所以现在你有了

E

看起来相当不错,但有人说'嘿,我们无法在mastertest进行更改,直到git checkout master git revert HEAD^ 合并为止;而且我们无法承受历史重写会导致的问题。因此...&#34;

A -- B -- E -- G -- ~E <--(master)
      \    \
       \    F <--(task1)
        \
         C -- D <--(test)

我们有

A -- B ------- E -- G -- ~E -- H -- O <--(master)
      \         \
       \         F <--(task1)
        \         \
         C -- D -- T <--(test)

每个分支上的所有内容都是正确的,因此继续工作

test

但是现在当你尝试将master合并到git时,会发生一些可怕的事情:E认为合并基数为master,因为test之间存在共同的祖先{1}}和EE是可以覆盖所有其他人/任何其他人无法联系到的人。{/ p>

因此,以foo.txt作为合并基础,他们的更改不会影响E(因为它已在foo.txt中创建),而我们的更改已删除~E(在foo.txt中)。因此合并结果没有master,这不是分支的变化 - 它已经在{{1}}的历史记录中发生了变化 - 因此公关报告对此没有任何说明

我知道这究竟发生了什么吗?不,我敢打赌这是非常像这样的吗?是。我可以拼出一个修复程序吗?不是真的,因为可能涉及到确切的步骤并依赖完全发生的事情。

现在我首先尝试确认问题是否与我所建议的基本相同。

答案 1 :(得分:0)

git merge合并了testmaster的所有更改,即test中已更改,添加和删除的文件将在master中更改,添加或删除}。

您要采取的措施是:

git checkout master
git merge test 
// if required: fix merge conflicts, shouldn't be required if `test` was in `sync` with master at the start of your sprint
git commit // if fixing merge conflicts were necessary
git push

在理想世界中,当mastertest在sprint开始时同步并且所有内容都可以合并回来时,两个分支将在您的sprint结束时再次同步。您的工作流程类似于gitflow - 只有您拨打分支test而不是develop

我的推荐:如果可能的话,当多个人在回购(分支)上工作时,请避免使用rebase。这是根据风险重写的历史。

github,TFS或VSTS等源代码管理工具也在合并而不是重新定位。

另请参阅文档https://git-scm.com/docs/git-merge