首页 文章

's the difference between ' git merge ' and ' git rebase'?

提问于
浏览
430

git mergegit rebase 有什么区别?

6 回答

  • 762

    假设最初有3个提交, ABC

    A-B-C

    然后开发人员Dan创建了commit D ,开发人员Ed创建了commit E

    A-B-C-D-E

    显然,这种冲突应该以某种方式解决 . 为此,有两种方法:

    MERGE

    A-B-C-D-E-M

    两个提交 DE 仍然在这里,但我们创建合并提交 M ,它继承了 DE 的更改 . 然而,这会产生钻石形状,许多人发现这种形状非常混乱 .

    REBASE

    A-B-C-D-E-R

    我们创建commit R ,其实际文件内容与上面的merge commit M 相同 . 但是,我们摆脱了提交 E ,就像它从未存在过一样(用点表示 - 消失线) . 由于这种消除, E 应该是开发人员Ed本地的,并且应该从未被推送到任何其他存储库 . rebase的优势在于避免了钻石形状,历史保持了良好的直线 - 大多数开发人员都喜欢这样!

  • 129

    我非常喜欢这个摘录自10 Things I hate about git(它在第二个例子中给出了一个关于rebase的简短解释):

    3.糟糕的文档手册页是一个万能的“f *** you”1 . 他们从计算机科学家的角度描述命令,而不是用户 . 例证:git-push - 更新远程引用以及相关对象
    以下是人类的描述:git-push - 将更改从本地存储库上载到远程存储库
    更新,另一个例子:(感谢cgd)git-rebase - 转发端口本地提交到更新的上游头
    翻译:git-rebase - 按顺序重新生成一系列提交,以便它们可以
    直接应用于头节点

    然后我们有

    git-merge - 一起加入两个或多个开发历史记录

    这是一个很好的描述 .


    1.未经审查的原件

  • 99

    就个人而言,我没有发现标准图表技术非常有用 - 箭头似乎总是指向我错误的方式 . (它们通常指向每个提交的“父”,最终会在时间上倒退,这很奇怪) .

    用文字解释:

    • 当你将你的分支放到他们的分支上时,你告诉Git看起来好像你干净地检查了他们的分支,然后从那里开始你的所有工作 . 这使得人们可以查看一个简洁,概念上简单的变更包 . 当分支上有新的更改时,您可以再次重复此过程,并且最终会得到一组干净的更改"on the tip" .

    • 当你将它们的分支分支到你的分支时,你将这两个分支历史绑定在一起 . 如果稍后再进行更多更改,则会开始创建一个交错的历史线程:一些更改,一些更改,一些更改 . 有些人发现这个混乱或不受欢迎 .

    由于我不明白的原因,Git的GUI工具从未花费太多努力来更清晰地呈现合并历史,抽象出各个合并 . 因此,如果您想要“干净的历史记录”,则需要使用rebase .

    我似乎记得曾经读过程序员的博客帖子,他们使用rebase和其他 never 使用rebase .

    示例

    我会用一个简单的例子来解释这个问题 . 假设您项目中的其他人正在使用用户界面,并且您正在编写文档 . 没有rebase,你的历史可能看起来像:

    Write tutorial
    Merge remote-tracking branch 'origin/master' into fixdocs
    Bigger buttons
    Drop down list
    Extend README
    Merge remote-tracking branch 'origin/master' into fixdocs
    Make window larger
    Fix a mistake in howto.md
    

    也就是说,在文档中间提交合并和UI提交 .

    如果您将代码重新设置为master而不是合并它,它将如下所示:

    Write tutorial
    Extend README
    Fix a mistake in howto.md
    Bigger buttons
    Drop down list
    Make window larger
    

    所有提交都在顶部(最新),然后是 master 分支的其余部分 .

    (免责声明:我是另一个答案中提到的"10 things I hate about Git"帖子的作者)

  • 13

    虽然接受和最受欢迎的答案很棒,但我还发现尝试用单词解释差异很有用:

    merge

    • “好吧,我们的存储库有两个不同的开发状态 . 让我们将它们合并在一起 . 两个父母,一个孩子 . “

    rebase

    • “将主分支(无论其名称)的更改提供给我的功能分支 . 通过假装我以后开始的功能工作来实现,实际上是在主分支的当前状态 . “

    • “改写我的历史更改以反映这一点 . “(需要强制推送它们,因为通常版本控制都是关于 not 篡改给定的历史记录)

    • “可能 - 如果我所做的改变与我的工作没什么关系 - 历史实际上不会有太大变化,如果我通过差异查看我的提交差异(你也可能会想到'补丁') . ”

    summary: 如果可能,rebase几乎总是更好 . 使重新集成到主分支更容易 .

    因为? ➝你的功能工作可以作为主要分支的一个大'补丁文件'(又名差异)呈现,而不必“解释”多个父母:至少两个,来自一个合并,但可能更多,如果有几次合并 . Unlike merges, multiple rebases do not add up. (另一个大加号)

  • 4

    Git rebase更接近合并 . rebase的区别在于:

    • 本地提交暂时从分支中删除 .

    • 运行git pull

    • 再次插入所有本地提交 .

    这意味着在所有远程提交之后,所有本地提交都会移动到最后 . 如果您有合并冲突,您也必须解决它 .

  • 34

    为了便于理解可以看到我的身材 .

    Rebase将更改提交哈希,因此如果您想避免大部分冲突,只需在该分支完成/完成时使用rebase稳定 .

    enter image description here

相关问题