git:合并两个分支:什么方向?

Alb*_*ert 61 git merge git-merge

我们有以下情况:

             A --- B --- C --- ... --- iphone
           /
  ... --- last-working --- ... --- master
Run Code Online (Sandbox Code Playgroud)

在上次工作和iPhone之间,进行了3​​2次提交.在last-working和master之间,做了很多提交.

我现在想要的是一个新的分支,我将iphone和当前的主人合并在一起.在以后的某个时间,这应该合并到主人.

首先,我计划做:

git checkout iphone -b iphone31
git merge master
Run Code Online (Sandbox Code Playgroud)

但后来我想,如果做得更好:

git checkout master -b iphone31
git merge iphone
Run Code Online (Sandbox Code Playgroud)

现在我想知道.结果会有什么不同?合并会有不同的表现吗?

我已经尝试了两种,正如我所料,我遇到了很多冲突,因为与主人相比,iphone真的很老了.现在我想知道合并它们的最简单方法.

也许甚至从大师开始并将每一次提交的iphone合并到它会更容易?喜欢这样做:

git checkout master -b iphone31
git merge A
git merge B
git merge C
...
git merge iphone
Run Code Online (Sandbox Code Playgroud)

最后,当这个合并完成时(即所有冲突都已解决且工作正常),我想这样做:

git checkout master
git merge iphone31
Run Code Online (Sandbox Code Playgroud)

hlo*_*dal 43

关于替代方案

git checkout iphone -b iphone31
git merge master
Run Code Online (Sandbox Code Playgroud)

git checkout master -b iphone31
git merge iphone
Run Code Online (Sandbox Code Playgroud)

他们会有同样的轻松或困难,就像争论一杯是半满或半空.

版本树感知

我们如何看待版本树在某种程度上只是我们的任意感知.假设我们有一个如下所示的版本树:

    A----------+
    |          |
    |          |
   \_/        \_/
    B          X
    |          |
    |          |
   \_/        \_/
    C          Y
    |
    |
   \_/
    D
    |
    |
   \_/
    E
Run Code Online (Sandbox Code Playgroud)

并且假设我们想要根据从C到E的变化从Y中检出新版本Z,但不包括从A到C的更改.

"哦,这很难,因为没有共同的起点." 好吧不是真的.如果我们只是将对象放置在图形布局中,就像这样

      /
    C+---------+
    | \        |
    |          |
   \_/         |
    D          B
    |         / \
    |          |
   \_/         |
    E          A
               |
               |
              \_/
               X
               |
               |
              \_/
               Y
Run Code Online (Sandbox Code Playgroud)

现在事情开始看起来很有希望了.请注意,我没有在这里更改任何关系,箭头都指向与上一张图片相同的方式,版本A仍然是公共基础.仅更改布局.

但现在想象一棵不同的树是微不足道的

    C'---------+
    |          |
    |          |
   \_/        \_/
    D          B'
    |          |
    |          |
   \_/        \_/
    E          A
               |
               |
              \_/
               X
               |
               |
              \_/
               Y
Run Code Online (Sandbox Code Playgroud)

任务只是通常合并版本E.

因此,您可以合并您想要的任何内容,唯一影响易用性或难度的是在您选择作为起点或公共基础的位置与您合并到的位置之间所做的更改的总和.您不仅限于使用版本控制工具建议的自然起点.

对于某些版本控制系统/工具,这可能并不简单,但如果所有其他方法都失败,那么通过签出版本C并将文件另存为file1,检查出版本E并将文件另存为file2,没有什么可以阻止您手动执行此操作,签出版本Y并将文件保存为file3,然后运行kdiff3 -o merge_result file1 file2 file3.

回答

现在针对您的具体情况,很难确切地说出会产生最少量问题的策略,但如果有许多变化会产生某种冲突,那么分割和合并较小的部分可能会更容易.

我的建议是,因为在last-working和iphone之间有32次提交,你可以例如从master的分支开始,然后在前16次提交中合并.如果结果太麻烦,请恢复并尝试合并8个第一次提交.等等.在最坏的情况下,您最终会逐个合并32个提交中的每个提交,但它可能比在一个单独的合并操作中处理所有累积的冲突更容易(在这种情况下,您正在使用非常不同的代码库) .

提示:

在纸上绘制一个版本树,并用箭头注释要合并的内容.如果你分几步完成这个过程,就可以完成它们的工作.这将使您更清楚地了解您想要实现的目标,迄今为止所做的工作以及剩下的工作.

我真的可以推荐KDiff3,它是一款出色的差异/合并工具.


Ryu*_*yuu 14

它们是有区别的.


始终在合并期间检查目标分支(即,如果将A合并到B,结帐B).


人们经常说合并方向并不重要,但这是错误的.虽然无论合并方向如何,结果内容都是相同的,但有几个方面是不同的:

  1. 生成的合并提交中列出的差异将根据方向而不同.
  2. 大多数分支可视化器将使用合并方向决定哪个分支是"主要".

详细说明,想象一下这个夸张的例子:

  • 您在1000次提交后从MASTER分支出来,并将其命名为DEVELOP(或者在跟踪分支方案中,您还没有获取相当长的时间).
  • 您在DEVELOP中添加一个提交.您知道此更改没有冲突.
  • 您想将更改推送到MASTER.
  • 您错误地将MASTER合并 DEVELOP中(即在合并期间检出DEVELOP).然后,您将DEVELOP推送为新的MASTER.
  • 生成的merge-commit中的差异将显示MASTER中发生的所有1000次提交,因为DEVELOP是参考点.

这些数据不仅没用,而且很难读出正在发生的事情.大多数可视化工具都会让你看起来像你的开发系统一直是主要的,有1000个提交.

我的建议是: 在合并期间始终检查目标分支(即,如果将A合并到B,结账B).

  • 如果您正在处理并行分支并希望定期从主分支引入更改,则检查并行分支.差异是有意义的 - 您将看到主分支中的更改已完成到您的分支.
  • 当您完成并行工作并希望将更改合并到主分支时,请检出主分支并与并行分支合并.diff再次有意义 - 它将向主分支显示您的并行更改.

在我看来,日志的可读性很重要.


sea*_*ges 6

最好的方法实际上取决于其他人是否拥有代码的远程副本.如果分支仅在本地计算机上,则可以使用rebase命令以交互方式将功能从功能分支应用到主服务器:

git checkout master -b iphone-merge-branch
git rebase -i iphone
Run Code Online (Sandbox Code Playgroud)

请注意,这会改变新的iphone-merge-branch分支的提交历史记录,这可能会导致其他任何人在以后尝试将更改提取到其结帐时出现问题.相比之下,merge命令将更改应用为新提交,这在协作时更安全,因为它不会影响分支历史记录.有关使用rebase的一些有用提示,请参阅此文章.

如果您需要保持提交历史记录同步,则最好执行合并.您可以使用git mergetool使用可视化差异工具逐个交互式修复冲突(可在此处找到相关教程):

git checkout master -b iphone-merge-branch
git merge iphone
git mergetool -t kdiff3
Run Code Online (Sandbox Code Playgroud)

第三种选择,如果你想要对进程进行绝对控制,那就是使用git cherry-pick.您可以使用gitk(或您最喜欢的历史查看器)查看iphone分支中的提交哈希值,记下它们,然后将它们单独挑选到合并分支中 - 随时修复冲突.可在此处找到此过程的说明.这个过程将是最慢的,但如果其他方法不能解决,可能是最好的后备选项:

gitk iphone
<note down the 35 commit SHA hashes in this branch>
git checkout master -b iphone-merge-branch
git cherry-pick b50788b
git cherry-pick g614590
...
Run Code Online (Sandbox Code Playgroud)

  • 不,结果非常不同.唯一相同的是你的最终工作副本.我建议你阅读我在解决方案中提到的关于rebase命令的一些背景知识的链接:http://www.gitready.com/intermediate/2009/01/31/intro-to-rebase.html (2认同)