我有两个分支:master
和develop
。当develop
的更改完成后,它们将合并到master
。
此时,分支应该同步。但是,我注意到master
中缺少一个文件但位于develop
分支上。 (看起来它以某种方式被删除但我使用git log -- myfile.txt
命令找不到任何证据。
我尝试将develop
合并到master
,但它表示没有任何内容可以合并。
> git checkout master
> git merge --no-ff develop
Already up-to-date
如何将develop
分支中的一个丢失文件重新合并到我们的master
分支中?
答案 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;:
...-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
尚不存在)。所以它取了M1
和B
之间的差异,这是没有的;以及M2
和B
之间的差异,这是M1
上的新发展。然后,它将这些差异组合在一起,将它们应用于B
的树,并进行新的合并提交D
。 develop
的树与M1
的树相同。
然而,这有点不同:
M2
在这种情况下,公共基数与以前一样M2
,但差异D
和...-*-o---M1--M2 <-- master
\ / /
A-B-C-D <-- develop
可能产生了一些东西。差异*
和*
显示分支o
上发生了什么。 Git通过将第二个更改集应用于*
的工作树来组合这两个,以进行合并提交B
。 develop
的工作树可能与o
的工作树不同,因为它还包含在提交M1
处发生的任何事情。但它可能是相同的,因为git&#34;结合了&#34;变化。
具体来说,如果从M1
到B
的差异包含 相同的变化,则变为与o
到{{ 1}},M1的树将匹配o
的树。如果没有,它就不会。也就是说,git只保留一个相同更改的副本。 (&#34;相同的&#34;这里意味着&#34;就git而言,它可以告诉&#34;它不是特别聪明。如果有一个改变就是添加单词&#34;闪亮的金属&#34 ;另一个变化是添加“#34;金属”这些词语,git认为这些是不同的。)
在任何情况下,第二次合并都会重复模式:比较B
与*
和o
与B
的工作树。无论第二个中是否已包含第一个中未包含的更改,请将这些更改应用于B
的工作树,并使用结果为M1
创建工作树。