关于程序员:Git进阶系列-5-Rebase-vs-Merge

32次阅读

共计 3025 个字符,预计需要花费 8 分钟才能阅读完成。

Git 是最风行的代码版本控制系统,这一系列文章介绍了一些 Git 的高阶应用形式,从而帮忙咱们能够更好的利用 Git 的能力。本系列一共 8 篇文章,这是第 5 篇。原文:Rebase vs. Merge: Integrating Changes in Git[1]

大多数开发人员都了解在 Git 中应用分支的重要性,事实上,本系列曾经有一篇对于 Git 分支策略的文章,解释了 Git 弱小的分支模型、不同类型的分支以及两种最常见的分支工作流。总而言之,在独立的容器中工作(即分支),是十分有用的,也是应用版本控制系统的次要起因之一。

本文咱们将钻研如何集成分支,如何将新代码增加回现有的开发线路中?有不同的办法能够实现这一点。在这篇“Git 进阶”系列的第五局部咱们要探讨 Git 中的集成更改,即合并和 rebase。

在咱们深刻细节之前,重要的是要了解这两个命令,git mergegit rebase。它们解决了雷同的问题,行将一个 Git 分支的更改集成到另一个分支,只是做法稍有不同。上面咱们从git merge 开始。

Git 进阶系列:

  1. 创立完满的提交
  2. Git 中的分支策略
  3. 基于 Pull Request 实现更好的合作
  4. 合并抵触
  5. Rebase vs Merge(本文)
  6. 交互式 Rebase
  7. Git 中的 Cherry-pick 提交
  8. 用 Reflog 复原失落的提交

了解合并

要将一个分支合并到另一个分支,能够应用 git merge 命令。假如在 ranch-B 上有一些新提交,当初咱们想把这个分支合并到另一个分支 branch-A 中。为此,能够这样输出:

$ git checkout branch-A
$ git merge branch-B

如此,Git 会在当前工作分支 (本例中为branch-A) 中创立一个新的合并提交,连贯两个分支的历史记录。为了实现这个工作,Git 须要查找三个提交:

  • 第一个是“公共先人提交(common ancestor commit)”。如果跟踪一个我的项目中两个分支的历史,总是至多有一个公共提交。此时,两个分支具备雷同的内容。在那之后,就向不同方向进化。
  • 另外两个乏味的提交是每个分支的端点,即它们的以后状态。请记住,集成的目标是组合两个分支的以后状态。因而,他们的最新订正当然很重要。

联合这三个提交能够执行咱们想要的集成。

无可否认,这是一个简化场景,两个分支中的一个 (branch-A) 自创立以来没有任何新的提交,这在大多数软件我的项目中是不太可能的。因而,它在本例中的最初一次提交也是 公共先人(common ancestor)

在这种状况下,集成非常简单,Git 能够将所有来自 branch-B 的新提交增加到公共先人提交之上。在 Git 中,这种最简略的集成模式称为“快进(fast-forward)”合并,而后两个分支共享完全相同的历史(并且不须要额定的“合并提交”)。

然而大多数状况下,两个分支将以不同的提交向前推动。咱们举一个更事实的例子:

为了集成,Git 必须创立一个蕴含所有更改的新提交,并留神分支之间的差别,这就是咱们所说的 合并提交(merge commit)

人工提交和合并提交

通常状况下,提交是由人精心创立的,是一个有意义的单元,只蕴含相干的变更,以及包含了上下文和正文的有意义的提交信息。

当初,合并提交有点不一样,它不是由开发人员创立的,而是由 Git 主动创立的。而且,合并提交不肯定蕴含“相干更改的语义汇合”。相同,它的目标只是连贯两个 (或更多) 分支。

如果想理解这样的主动合并操作,必须查看所有分支的历史以及各自的提交历史。

Rebase 集成

在探讨 rebase 之前,先说分明一点: rebase 并不比合并更好或更差,只是不同而已。兴许你只须要通过合并集成分支,就能够实现工作,甚至不须要思考 rebase。不过,了解 rebase 是做什么的,并理解它的优缺点,的确很有帮忙。兴许你会在某个我的项目中遇到某个问题,而 rebase 恰好很有帮忙…

好吧,咱们开始!还记得刚刚讲的主动合并提交吗?有些人不太喜爱这些,宁愿不必。另外一些开发人员喜爱我的项目历史看起来像一条直线,没有任何迹象表明它在某个点上被分成了多个分支,即便这些分支曾经被集成了。这基本上就是 Git rebase 过程中产生的事件。

一步一步 rebase

让咱们逐渐介绍 rebase 操作。和后面的例子一样,一开始是这样的:

咱们想要将 branch-B 的更改集成到 branch-A 中,但这次是用 rebase,而不是合并。理论的 Git 命令非常简单:

$ git checkout branch-A
$ git rebase branch-B

相似于 git merge 命令,只须要通知 git 想要集成哪个分支。咱们来看看幕后故事……

第一步,Git 将“删除”产生在公共先人提交之后的所有对 branch-A 分支的提交。别放心,它们不会被抛弃,能够将这些提交视为被临时保留在一个平安的中央。

第二步,Git 利用来自 branch-B 的新提交。此时,两个分支临时看起来完全相同。

最初,集成那些“暂存”的提交 (来自branch-A 的新提交)。因为它们位于 branch-B 分支的顶部,所以是 rebase 的。

因而,我的项目历史看起来就像是在一条直线上进行开发,不存在蕴含所有合并更改的合并提交,并且保留了原始提交构造。

rebase 的潜在隐患

还有一件事对于了解 Git rebase 很重要,它重写了提交历史 。再看一下最初一张图表,提交C3* 带有星号,尽管 C3*C3具备雷同的内容,但实际上是不同的提交。为什么?因为它在 rebase 之后有一个新的父提交。在 rebase 之前,C1是父提交。在 rebase 之后,父提交是C4,它被 rebase 到了C4

一个提交只有大量重要属性,比方作者、日期、变更集和父提交,更改任何这些信息都会创立一个全新的提交,有一个新的 SHA- 1 哈希 ID。

对于尚未公布的提交,这样重写历史记录不是问题。然而,如果正在重写的是曾经推送到远端代码库的提交,可能会遇到麻烦。兴许其他人的工作是基于最后的 C3 提交的,当初它忽然不存在了……

为了远离麻烦,这里有一个应用 rebase 的简略规定: 永远不要在公共分支上应用 rebase,比方说曾经被推送到远端代码库的提交!相同,只在将它集成到共享的团队分支之前,才应用 git rebase 来清理本地提交历史。

集成就是所有!

归根到底,merge 和 rebase 都是有用的 Git 策略,用哪个取决于想要实现的指标。合并是非破坏性的,因为合并不会扭转现有的历史。另一方面,rebase 能够通过防止不必要的合并提交来帮忙清理我的项目历史记录。只有记住不要在公共分支中这样做,从而防止烦扰其余开发人员。

如果想更深刻理解高级 Git 工具,能够收费查看“Advanced Git Kit[3]”: 这是对于分支策略、交互式 Rebase、Reflog、子模块等主题的短视频汇合。

References: \
[1] Rebase vs. Merge: Integrating Changes in Git: https://css-tricks.com/rebase-vs-merge-integrating-changes-in…

你好,我是俞凡,在 Motorola 做过研发,当初在 Mavenir 做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI 等技术始终保持着浓重的趣味,平时喜爱浏览、思考,置信继续学习、一生成长,欢送一起交流学习。\
微信公众号:DeepNoMind

本文由 mdnice 多平台公布

正文完
 0