建议何时使用Git rebase与Git merge?
成功重新创建数据库后,是否仍需要合并?
建议何时使用Git rebase与Git merge?
成功重新创建数据库后,是否仍需要合并?
当前回答
我什么时候使用git rebase?几乎不会,因为它改写了历史。gitmerge几乎总是首选,因为它尊重项目中实际发生的事情。
其他回答
当您正在处理分支并在其间合并了一些其他工作时,Rebase是有用的-合并将创建更改,从而使diff受到污染,因此更难阅读。
如果您重新设置分支的基值,那么您的提交将应用于要重新设置基值的分支的顶部,这使得查看更容易,并且diff输出更干净。
这里的很多答案都说,合并会将所有提交转换为一个,因此建议使用rebase来保存提交。这是不正确的。如果你已经提交了,那是个坏主意。
合并不会消除提交。合并保留历史!(看看gitk)热巴改写了历史,这是你推后的坏事。
使用merge,而不是在已经推送的情况下重新设置基址。
这是Linus(Git的作者)对它的看法(现在托管在我自己的博客上,由Wayback Machine恢复)。这真是一本好书。
或者你可以在下面阅读我自己的版本。
在主节点上重新分配分支:
提供了如何创建提交的错误想法用一堆可能没有经过良好测试的中间提交来污染master实际上可能会在这些中间提交上引入构建中断,因为在创建原始主题分支和重新创建主题分支之间对master进行了更改。这使得在master中找到好地方结账变得困难。导致提交的时间戳与其在树中的时间顺序不一致。因此,您将看到提交A在主提交B之前,但提交B是先编写的。(什么?!)产生更多的冲突,因为主题分支中的每个提交都可能涉及合并冲突,这些冲突必须单独解决(关于每个提交中发生的情况,请进一步查看历史)。是对历史的改写。如果正在重新创建的分支被推到任何地方(与除您之外的任何人共享),那么自您改写历史以来,您已经将拥有该分支的所有其他人都搞砸了。
相反,将主题分支合并为主分支:
保留主题分支创建位置的历史记录,包括从主分支到主题分支的任何合并,以帮助保持其最新状态。您可以准确地了解开发人员在构建时使用的代码。master是一个主要由合并组成的分支,而这些合并提交中的每一个都是历史上可以安全检出的“好点”,因为这就是主题分支可以集成的地方。主题分支的所有单独提交都会被保留,包括它们位于主题分支中的事实,因此隔离这些更改是很自然的,您可以在需要时钻取。合并冲突只需解决一次(在合并时),因此在主题分支中进行的中间提交更改不必单独解决。可以平滑地进行多次。如果您定期将主题分支集成到master,人们可以继续在主题分支上进行构建,并且可以继续独立地进行合并。
Gitrebase用于使历史中的分支路径更清晰,存储库结构更线性。
它还用于将您创建的分支保持为私有,因为在重新创建基础并将更改推送到服务器之后,如果您删除了分支,则不会有您曾处理过的分支的证据。因此,您的分支现在是您的本地关注点。
在进行重新基化之后,我们还消除了一个额外的提交,这是我们用来查看是否进行正常合并的。
是的,在成功的rebase之后仍然需要进行合并,因为rebase命令只是将您的工作放在您在rebase过程中提到的分支之上,比如master,并将分支的第一次提交作为master分支的直接后代。这意味着我们现在可以进行快速合并,将更改从该分支带到主分支。
TL;博士
如果您有任何疑问,请使用merge。
简短回答
重新基准和合并之间的唯一区别是:
生成的历史树结构(通常只有在查看提交图时才明显)不同(一个有分支,另一个没有分支)。合并通常会创建一个额外的提交(例如树中的节点)。合并和重新基础将以不同的方式处理冲突。Rebase将一次提交一个冲突,而merge将一次显示所有冲突。
因此,简单的答案是根据您希望的历史外观选择重新基准或合并。
长答案
在选择要使用的操作时,需要考虑以下几个因素。
您从中获得更改的分支是否与团队之外的其他开发人员共享(例如,开源、公共)?
如果是,请不要重新设置基准。Rebase会破坏分支,除非他们使用git pull-Rebase,否则这些开发人员将拥有损坏/不一致的存储库。这是一个很快让其他开发人员感到不安的好方法。
您的开发团队有多熟练?
回扣是一种破坏性操作。这意味着,如果不正确应用它,您可能会丢失已提交的工作和/或破坏其他开发人员存储库的一致性。
我曾在团队中工作过,这些团队中的开发人员都来自一个公司能够负担得起专门的员工来处理分支和合并的时代。这些开发人员对Git了解不多,也不想了解太多。在这些团队中,我不会因为任何原因而冒险建议重新定基。
分支本身是否表示有用的信息
一些团队使用每个功能的分支模型,其中每个分支表示一个功能(或错误修复或子功能等)。在这个模型中,分支帮助识别相关提交的集合。例如,可以通过恢复该分支的合并来快速恢复功能(公平地说,这是一个罕见的操作)。或者通过比较两个分支来区分一个特性(更常见)。Rebase会破坏分支,这并不简单。
我也曾在使用每个开发人员分支模型的团队中工作过(我们都去过)。在这种情况下,分支本身不传递任何附加信息(提交已经包含作者)。换基不会有什么害处。
是否出于任何原因要还原合并?
与恢复合并相比,恢复(如撤消)重基相当困难和/或不可能(如果重基发生冲突)。如果您认为有机会恢复,请使用merge。
你是团队成员吗?如果是的话,你愿意在这一分支机构采取“要么全有要么全无”的方法吗?
需要使用相应的git pull--Rebase来拉动Rebase操作。如果你是自己工作,你可能会记得在适当的时候应该使用哪一个。如果你在一个团队中工作,这将很难协调。这就是为什么大多数rebase工作流建议对所有合并使用rebase(以及git pull--rebase对所有合并)。
常见的神话
合并销毁历史记录(压缩提交)
假设您有以下合并:
B -- C
/ \
A--------D
有些人会说合并“破坏”了提交历史,因为如果只查看主分支(A-D)的日志,就会错过B和C中包含的重要提交消息。
如果这是真的,我们就不会有这样的问题了。基本上,除非您明确要求不要看到B和C(使用--firstparent),否则您将看到它们。这很容易自己尝试。
Rebase允许更安全/更简单的合并
这两种方法的合并方式不同,但并不清楚其中一种总是优于另一种,这可能取决于开发人员的工作流程。例如,如果开发人员倾向于定期提交(例如,当他们从工作过渡到家庭时,他们可能一天提交两次),那么给定分支可能会有很多提交。其中许多提交看起来可能与最终产品不太相似(我倾向于对每个特性进行一次或两次重构)。如果其他人正在处理一个相关的代码领域,他们试图重新调整我的更改,这可能是一个相当乏味的操作。
热巴更酷/更性感/更专业
如果您想将rm别名为rm-rf以“节省时间”,那么可能需要重新设置基准。
我的两美分
我一直认为有一天我会遇到这样一个场景,Git rebase是解决这个问题的绝佳工具。就像我认为我会遇到这样一个场景,Git reflog是一个很好的工具,可以解决我的问题。我已经在Git工作了五年多了。这还没有发生。
混乱的历史对我来说从来都不是一个问题。我从来没有像读一本令人兴奋的小说那样阅读我的承诺历史。大多数时候,我需要一段历史,无论如何,我都会使用Git责备或Git平分。在这种情况下,合并提交实际上对我很有用,因为如果合并引入了问题,那对我来说就是有意义的信息。
更新(2017年4月)
我觉得有义务提及我个人对使用rebase的态度有所软化,尽管我的一般建议仍然有效。我最近与Angular 2 Material项目进行了很多互动。他们使用rebase来保持非常干净的提交历史。这使我能够非常容易地看到是什么提交修复了给定的缺陷,以及该提交是否包含在发布中。它是正确使用rebase的一个很好的例子。
Pro Git的书在重新设置基础页面上有一个很好的解释。
基本上,合并将进行两次提交并合并它们。
一个重基将转到这两者的共同祖先,并在彼此之上逐步应用更改。这使得历史更加“清晰”和线性。
但当您重新创建基准时,您将放弃以前的提交并创建新的提交。因此,您永远不应该重新设置公共存储库的基础。其他在存储库中工作的人会恨你。
仅出于这个原因,我几乎完全合并了。99%的时候,我的分支机构没有太大的差异,所以如果有冲突,只会发生在一两个地方。