git merge说已经是最新的但是在分支机构中有一个承诺的差异

时间:2014-03-28 20:51:07

标签: git git-merge

我有两个分支:masterdevelop。当develop的更改完成后,它们将合并到master

此时,分支应该同步。但是,我注意到master中缺少一个文件但位于develop分支上。 (看起来它以某种方式被删除但我使用git log -- myfile.txt命令找不到任何证据。

我尝试将develop合并到master,但它表示没有任何内容可以合并。

> git checkout master
> git merge --no-ff develop
Already up-to-date

如何将develop分支中的一个丢失文件重新合并到我们的master分支中?

1 个答案:

答案 0 :(得分:3)

你根本不合并这个;相反,您只需从develop分支中提取所需的文件,并将其提交到master分支。 (我假设"丢失"文件从未被合并过,可能是由于任何人做出最后的错误 - 任何合并,或者可能是有意的。)从另一个分支中提取文件,在master上:

# run "git status" here to make sure you're on master
# and have no other changes you want to commit first!
git checkout develop -- path/to/file

因为这种结账会写出"通过"在索引中,新文件现在已暂存并准备提交到分支master

下面的讨论。


合并实际上不会同步分支(更具体地说,它并不意味着它们将具有相同的工作树,无论如何)。所有git merge都会查看提交历史记录,以查看应该合并更改(如果有)的内容。这意味着它必须找到最近的共同历史。让我们绘制一些提交图片段来说明这一点。

git checkout master

选择一些特定的提交,然后:

git merge <sha1-or-other-identifier-like-develop>

告诉git从已识别的SHA-1开始,并查看该分支的最后位置&#34;以及&#34; master。这是&#34;合并基础的&#34;:

的SHA-1
...-o-*-o-o-o   <-- master
       \
        o-o     <-- develop

合并基础是此处标记为*的提交,*标识的行develop之后的提交不在master标识的行上这个序列需要合并。

然而:

...-o-*-o-o-o   <-- master
       `---___
              `---- develop

此处,develop直接指向提交*(合并基础,再次)。从那以后develop下面没有master下面没有提交的提交。所以这是Already up-to-date。同样地:

...-o-o-o-M   <-- master
     \   /
      o-*     <-- develop

如果develop最近合并,您会看到这种情况:master上有合并提交,我已标记为M。合并基础仍然是提交*;直接为该提交开发点,合并提交M也是如此。因此,没有任何内容可以合并(develop上没有提交master上的提交,由merge-commit M提供。)

如果(git认为)需要合并 ,git会根据当前分支的最新提交({{1}的尖端)来区分基础(*提交)并且还根据您要求合并的提交来区分基础(在这种情况下,是master的提示)。然后(实质上)查看两个差异,在第二个差异中进行任何更改,然后将它们应用到工作树中。

如果一切顺利,git通常会在此时进行合并提交(尽管你可以抑制它)。如果没有,它会因合并冲突而停止并让你自己解决问题,之后你自己做了#34; git commit&#34;提交合并。

合并提交的工作树包括任何git自动解析,以及之后暂存的任何内容,如果您手动执行提交。一旦合并提交本身存在,提交图将是这样的,git将认为不需要后续合并(例如,在向develop添加更多提交之前)。

如果(git认为)合并是而不是,它当然会什么都不做。


最后两张插图:

develop

...-*-----M1--M2 <-- master \ / / A-B-C-D <-- develop 中执行两次git merge --no-ff develop后,master没有进行干预提交,就会出现此模式:

第一次合并以master开头,因为公共合并基础(*M1尚不存在),因此它找到了M2和{{之间的变化1}}。 *和它自身之间没有变化,因此合并很简单:git将这些更改添加到B(提供与*中相同的工作树)并进行合并提交{{1 }}

第二次合并以提交*开始,因为合并基础(B尚不存在)。所以它取了M1B之间的差异,这是没有的;以及M2B之间的差异,这是M1上的新发展。然后,它将这些差异组合在一起,将它们应用于B的树,并进行新的合并提交Ddevelop的树与M1的树相同。

然而,这有点不同:

M2

在这种情况下,公共基数与以前一样M2,但差异D...-*-o---M1--M2 <-- master \ / / A-B-C-D <-- develop 可能产生了一些东西。差异**显示分支o上发生了什么。 Git通过将第二个更改集应用于*的工作树来组合这两个,以进行合并提交Bdevelop的工作树可能与o的工作树不同,因为它还包含在提交M1处发生的任何事情。但它可能是相同的,因为git&#34;结合了&#34;变化。

具体来说,如果从M1B 的差异包含 相同的变化,则变为与o到{{ 1}},M1的树将匹配o的树。如果没有,它就不会。也就是说,git只保留一个相同更改的副本。 (&#34;相同的&#34;这里意味着&#34;就git而言,它可以告诉&#34;它不是特别聪明。如果有一个改变就是添加单词&#34;闪亮的金属&#34 ;另一个变化是添加“#34;金属”这些词语,git认为这些是不同的。)

在任何情况下,第二次合并都会重复模式:比较B*oB的工作树。无论第二个中是否已包含第一个中未包含的更改,请将这些更改应用于B的工作树,并使用结果为M1创建工作树。