GIT:从两个分支创建文件的合并版本

时间:2019-05-04 12:30:19

标签: git

我不喜欢用3路方式从两个分支创建文件的合并版本,但是我不知道如何。

3 个答案:

答案 0 :(得分:1)

创建一个新分支

git branch new_branch

git checkout new_branch

git merge old_branch1

git merge old_branch2

new_branch现在包含合并的版本,而old_branch1和old_branch2包含以前的版本。

答案 1 :(得分:1)

在当前分支中,创建一个新分支:

<div class="card-white"> <div class="footer"> <ul> <li> <a href="https://www.facebook.com/alexandre.auriol/" target="_blank"><i class="fab fa-facebook-square"></i>Facebook</a> </li> <li> <a href="https://www.instagram.com/alexandre.auriol/" target="_blank"><i class="fab fa-instagram"></i>Instagram</a> </li> </ul> </div> </div>

之后,与另一个分支合并:

git checkout -b new_branch

答案 2 :(得分:0)

请记住,合并是关于合并工作。我认为,例如,如果您认为合并是有帮助的,

  

Alice对她的文件做了一些工作,而Bob对他的文件做了一些工作,现在Alice,Bob甚至是第三人Carol想要将这两个结合起来工作范围。

Git通常一次处理整个 commits ,而不处理单个文件。如果运行git merge,则将合并 commits ,而不是 files 。也就是说,您可以git checkout进行Alice的最新提交,然后运行git merge Bob,Git会找到Alice和Bob的起始位置,查看他们对所有文件进行了什么处理,然后合并全部

如果您确实想对仅一个文件进行三向合并,则需要获取该文件的三个版本。毕竟,这就是三向合并的含义:每个要合并的文件都获得三个版本,然后使用这三个输入版本得出最终的合并版本。

文件级合并操作的三个输入是:

  • 文件的--ours版本。如果您要git checkout Alice(进入Alice分支),那将是Alice的最新消息。

  • 文件的--theirs版本。如果您要运行git merge Bob(从Bob的分支合并),那将是Bob的最新消息。

  • 文件的合并基础版本。那是Alice和Bob都开始使用的文件的版本。这是困难的部分:爱丽丝和鲍勃都从哪个版本的文件 did 开始?

查找合并基础,并让该合并基础用于所有文件,而不只是一个,git merge会为您服务。当您运行git merge时,Git使用历史记录(存储库中的提交)来找到合并基础 commit ,即两个分支上共享最好的提交。如果我们记得每次提交都会自动记住自己的父母,那么我们可以看到它是如何工作的:

             o--o--A   <-- alice
            /
...--o--o--*
            \
             o--o--B   <-- bob

Alice和Bob都从提交*开始。此后,爱丽丝在 her 分支上进行了3次提交,鲍勃在 his 上进行了3次提交。我在这里将Alice的最新标签为提交A,将Bob的最新标签为提交B,尽管这两个标签(当然也包括提交*)都具有一些难看的哈希ID作为他们的真实姓名。

提交*两个分支上,并且由于它是共享提交,并且提交是 all 文件,很明显,当时Alice和Bob在每个文件中都有相同的内容。因此,git merge命令将从提交*中获取每个文件,并将每个此类文件与提交A中的每个文件进行比较。无论这里发生了什么变化,爱丽丝都发生了变化。然后,Git将比较*中的每个文件与提交B中的每个文件。无论这里发生了什么变化,鲍勃都发生了变化。

对于与git merge相比在AB中进行了更改的每个文件,{em}都将使用*命令更改每个文件。也就是说,如果Alice和Bob 两者都更改了README.md,则Git将合并这些更改。如果Alice更改了alice.txt,而Bob没有更改,则Git只会接受Alice的更改。如果Bob更改了blue.py而Alice没有更改,那么Git只会接受Bob的更改。

已将所有这些更改组合在一起(假设将所有工作组合在一起),Git会将组合的更改应用于*中的所有内容。生成的文件现在适合进行 new 提交。新的提交是 merge commit ,这是特殊的,因为它有两个父母而不是通常的父母:而不是记住我的父母是commit A my父是提交B ,新提交会记住这两个:

             o--o--A
            /       \
...--o--o--*         M
            \       /
             o--o--B

新的提交M进入您现在已签出的任何分支。如果是分支alice,则结果为:

             o--o--A
            /       \
...--o--o--*         M   <-- alice (HEAD)
            \       /
             o--o--B   <-- bob

如果您首先创建一个 new 分支(例如carol),则 还要指向首先提交A

             o--o--A   <-- alice, carol (HEAD)
            /
...--o--o--*
            \
             o--o--B   <-- bob

然后新的提交M将名称carol更改为指向M

             o--o--A   <-- alice
            /       \
...--o--o--*         M   <-- carol (HEAD)
            \       /
             o--o--B   <-- bob

请记住,M中的 all 个文件是合并 all 所做的更改的结果。棘手的部分是查找更改,因为提交是快照,而这样做的技巧是找到快照*(合并基础)。然后,Git将快照*与快照A进行了比较:

git diff --find-renames <hash-of-*> <hash-of-A>    # what Alice changed

并针对快照B重复此操作:

git diff --find-renames <hash-of-*> <hash-of-B>    # what Bob changed

然后合并将三个快照中所有所有文件的这些更改组合起来,以构建合并提交M,该合并提交进入当前分支:带有HEAD的分支附加到它。

结论1

要合并AB中的 all 个文件而不影响任何其他分支,可以创建一个 new 分支以指向任一提交A或提交B,然后使用指定两次提交中的另一个的任何名称或哈希ID运行git merge。如果合并成功,则新的合并提交M将指向AB,并且将分别位于新分支上。

要合并AB中的所有文件,同时将新的合并提交放入分支alice(当前提交A)或bob(当前提交B),签出所需的分支并使用另一个分支的名称运行git merge。如果合并成功,您的新合并提交M将同时指向AB,就像其他情况一样,但是这次合并提交将位于{{1 }}或alice,而不是位于您未创建的新分支上。

结论2

如果您确实只想合并提交bobA中的一个文件,则不能使用B来做到这一点:它做得太多了;它将合并所有文件。有一个Git命令可以合并一个文件:

git merge

将完成这项工作。但它需要三个输入文件。它需要您要合并其更改的文件的合并基础版本。找到合并的基本版本,以及您要合并的其他两个版本。将它们放入三个文件中,例如git merge-file file.basefile.mine。然后运行:

file.theirs

Git会将git merge-file file.mine file.base file.theirs file.base进行比较以查看您所更改的,并将file.minefile.base进行比较以查看其 已更改。然后它将尝试合并这两个更改,将合并的更改应用于file.theirs,然后将结果写入file.base

这当然是file.mine每个文件所做的工作。 git merge只是为您找到了三个 文件,并自动完成了所有工作。