建议何时使用Git rebase与Git merge?

成功重新创建数据库后,是否仍需要合并?


当前回答

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的一个很好的例子。

其他回答

我什么时候使用git rebase?几乎不会,因为它改写了历史。gitmerge几乎总是首选,因为它尊重项目中实际发生的事情。

Pro Git的书在重新设置基础页面上有一个很好的解释。

基本上,合并将进行两次提交并合并它们。

一个重基将转到这两者的共同祖先,并在彼此之上逐步应用更改。这使得历史更加“清晰”和线性。

但当您重新创建基准时,您将放弃以前的提交并创建新的提交。因此,您永远不应该重新设置公共存储库的基础。其他在存储库中工作的人会恨你。

仅出于这个原因,我几乎完全合并了。99%的时候,我的分支机构没有太大的差异,所以如果有冲突,只会发生在一两个地方。

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的一个很好的例子。

Gitrebase用于使历史中的分支路径更清晰,存储库结构更线性。

它还用于将您创建的分支保持为私有,因为在重新创建基础并将更改推送到服务器之后,如果您删除了分支,则不会有您曾处理过的分支的证据。因此,您的分支现在是您的本地关注点。

在进行重新基化之后,我们还消除了一个额外的提交,这是我们用来查看是否进行正常合并的。

是的,在成功的rebase之后仍然需要进行合并,因为rebase命令只是将您的工作放在您在rebase过程中提到的分支之上,比如master,并将分支的第一次提交作为master分支的直接后代。这意味着我们现在可以进行快速合并,将更改从该分支带到主分支。

在合并/重新基础之前:

A <- B <- C    [master]
^
 \
  D <- E       [branch]

git合并主机后:

A <- B <- C
^         ^
 \         \
  D <- E <- F

git rebase master之后:

A <- B <- C <- D' <- E'

(A、B、C、D、E和F为提交)

在Git基础教程中可以找到这个例子以及更多关于Git的详细信息。