“git merge”和“git rebase”有什么区别?
git merge
和git rebase
什么区别?
假设原来有3个提交, A
, B
, C
:
然后开发者Dan创build了提交D
,而开发者Ed创build了提交E
:
显然,这个冲突应该以某种方式解决。 为此,有两种方法:
MERGE :
这两个提交D
和E
仍然在这里,但我们创build合并提交M
,inheritanceD
和E
变化。 但是,这样会产生钻石形状,许多人都觉得很混乱。
REBASE :
我们创build提交R
,实际的文件内容与上面的合并提交M
相同。 但是,我们摆脱了提交E
,就像它从来没有存在(由点 – 消失线表示)。 由于这个问题, E
应该是开发人员Ed的本地人员,并且从来没有被推到任何其他的仓库。 重build的好处是避免了钻石的形状,历史保持不错的直线 – 大多数开发人员都喜欢它!
我真的很喜欢这个我讨厌git的10件事的摘录(在第二个例子中,它给出了rebase的简单解释):
3.蹩脚的文件
手册页是一个全能的“f *** you” 1 。 他们从计算机科学家的angular度来描述命令,而不是用户。 例如:
git-push – Update remote refs along with associated objects
这里是对人类的描述:
git-push – Upload changes from your local repository into a remote repository
更新,另一个例子:(谢谢cgd)
git-rebase – Forward-port local commits to the updated upstream head
翻译:
git-rebase – Sequentially regenerate a series of commits so they can be applied directly to the head node
然后我们有
git-merge - Join two or more development histories together
这是一个很好的描述。
未经审查的原件
就我个人而言,我不觉得标准的图表技术非常有用 – 箭头似乎总是给我指出错误的方式。 (他们通常指向每个提交的“父母”,最后是时间倒退,这很奇怪)。
用文字来解释:
- 当你把你的分支重新分支到分支上时,你告诉Git使它看起来好像你干净地检查了他们的分支,然后从那里开始所有的工作。 这使得一个干净的,概念上简单的变化包可以被人们审查。 当分支有新的改变时,你可以再次重复这个过程,并且总是最终得到一组干净的“分支尖端”变化。
- 当你把分支合并到你的分支时,你将这两个分支历史联系在一起。 如果稍后再做更多的更改,则会开始创build一个交错的历史logging:其中一些更改,一些更改以及一些更改。 有些人觉得这很混乱或不可取
由于我不明白的原因,Git的GUI工具从来没有做过太多的工作来更清晰地呈现合并历史,抽象出单个合并。 所以如果你想要一个“清洁历史”,你需要使用rebase。
我似乎回想起只读过使用rebase的程序员的博客文章和其他从未使用rebase的博客post。
例
我会试着用一个简单的例子来解释这个。 假设您的项目中的其他人正在使用用户界面,并且正在编写文档。 没有重build,你的历史可能看起来像这样:
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。
如果您将代码重新编码到主服务器上而不是合并它,则会显示如下所示:
Write tutorial Extend README Fix a mistake in howto.md Bigger buttons Drop down list Make window larger
所有提交都在顶部(最新),其次是master
分支的其余部分。
( 免责声明:我是另外一个答案中提到的“我讨厌Git的10件事”的作者 )
虽然接受和最有回报的答案是伟大的,我另外发现它是有用的试图解释仅仅用字的差异:
合并
- “好吧,我们有两个不同的发展状态,我们的存储库。 让我们把它们合并在一起。 两个父母,一个孩子。“
变基
- “把主分支的变化(不pipe它的名字)给我的特性分支。 假装我的特色工作是在晚些时候开始的,实际上就是主要分支的现状。
- “重写我的变化历史以反映这一点” (需要强制推送它们,因为通常版本控制都不是篡改给定的历史logging)
- “”如果我所看到的变化与我的工作无关,历史实际上不会发生太大的变化,如果我通过差异来看待我的承诺(你也可能会想到“补丁”)。
总结:如果可能,rebase几乎总是更好。 更容易地重新集成到主分支。
因为? ➝您的特色工作可以作为一个大的“补丁文件”(aka diff)表示,而不必“解释”多个父母:至less有两个来自一个合并,但可能还有更多,如果有几次合并。 与合并不同,多个rebase不加起来。 (另一大优势)
Git rebase更接近合并。 rebase的区别是:
- 本地提交从分支临时移除。
- 运行git pull
- 再次插入你所有的本地提交。
这意味着在所有的远程提交之后,所有的本地提交都会被移动到最后。 如果你有合并冲突,你也必须解决它。