迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 操作系统 >

Git merge 和 Git rebase 的比较

作者:迹忆客 最近更新:2021/12/20 浏览次数:

git rebase 命令对于初学者来说号称是 Git 中的巫术,但是如果小心使用,其实它上可以让开发团队的生活变得更轻松。 在本文中,我们将 git rebase 与相关的 git merge 命令进行比较,并确定将 rebase 合并到典型 Git 工作流程中的所有的可能的机会。

概念概述

首先要了解的是, git rebase 解决了与 git merge 相同的问题。 这两个命令都旨在将更改从一个分支集成到另一个分支 - 只是二者进行的方式非常不同。

考虑一下当我们开始在专用分支中处理新功能时会发生什么,然后另一个团队成员使用新提交更新主分支。 这会导致历史分叉,任何使用 Git 作为协作工具的人都应该熟悉这一点。

一个分支的提交历史
一个分支的提交历史

现在,假设 main 中的新提交与我们正在处理的功能相关。 要将新提交合并到我们的 feature 分支中,有两个选择:mergerebase

使用 Merge

最简单的选择是使用以下命令将 main 分支合并到 feature 分支中:

$ git checkout feature
$ git merge main

或者,可以将其压缩为一行:

$ git merge feature main

这会在 feature 分支中创建一个新的“合并提交”,将两个分支的历史联系在一起

main 分支合并至 feature 分支
main 分支合并至 feature 分支

Merge 很好,因为它是一种非破坏性操作。 现有的分支不会以任何方式改变。 这避免了 rebase 的所有潜在问题(在下面讨论)。

另一方面,这也意味着每次需要合并上游更改时,feature 分支都会有一个无关的合并提交。 如果 main 非常活跃,这可能会严重影响 feature 分支的历史记录。 虽然可以使用高级命令 git log 来缓解这个问题,但它会让其他开发人员难以理解项目的历史。

使用 Rebase

作为 merge 的替代方法,我们可以使用以下命令将 feature 分支重新定位到 main 分支上:

$ git checkout feature
$ git rebase main

这将整个 feature 分支移动到 main 分支的顶端,有效地将所有新提交合并到主分支中。 但是,rebase 不是使用合并提交,而是通过为原始分支中的每个提交创建全新的提交来重写项目历史记录。

feature 分支变基到 main分支
feature 分支变基到 main分支

变基的主要好处是我们可以获得更清晰的项目历史记录。 首先,它消除了 git merge 所需的不必要的合并提交。 其次,正如在上图中所看到的,rebase 还会产生完美的线性项目历史——我们可以按照功能的提示一直到项目的开始,而无需任何分支。 这样可以更轻松地使用 git log、git bisect 和 gitk 等命令导航我们的项目。

但是,这个原始提交历史有两个权衡:安全性和可追溯性。 如果不遵循 Rebase 的黄金法则,重写项目历史可能会给协作工作流程带来灾难性的后果。 而且,不太重要的是,rebase 丢失了合并提交提供的上下文——我们无法看到上游更改何时合并到feature中。

交互式 Rebase

交互式变基使我们有机会在将提交移动到新分支时更改提交。 这比自动变基更强大,因为可以对分支提交历史的进行完全控制。 通常,这用于在将 feature 分支合并到 main 分支之前清理混乱的历史记录。

要开始交互式变基会话,可以在 git rebase 命令后面加上 -i 选项:

$ git checkout feature
$ git rebase -i main

这将打开一个文本编辑器,列出所有将要移动的提交:

pick 33d5b7a Message for commit #1
pick 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3

上面准确定义了执行 rebase 后分支的内容。 通过更改 pick 命令和/或重新排序条目,我们可以使分支的历史记录看起来像想要的任何内容。 例如,如果第二次提交修复了第一次提交中的一个小问题,我们可以使用 fixup 命令将它们压缩为单个提交:

pick 33d5b7a Message for commit #1
fixup 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3

当保存并关闭文件时,Git 将根据我们的指示执行 rebase,从而生成如下所示的项目历史记录:

使用交互式 rebase 压缩提交
使用交互式 rebase 压缩提交

像这样减少无关紧要的提交会使我们的 feature 历史更容易理解。 这是 git merge 根本无法做到的。

使用 rebase 的黄金法则

一旦你理解了 rebase 是什么,最重要的是学习什么时候不要使用rebase。 git rebase 的黄金法则是永远不要在公共分支上使用。

例如,考虑一下如果将 main 重新变基到 feature 分支上会发生什么:

变基main分支
变基main分支

rebase 将 main 中的所有提交移动到 feature 的顶端。 问题是这仅发生在您的存储库中。 所有其他开发人员仍在使用原始main分支的程序。 由于 rebase 会产生全新的提交,Git 会认为你的主分支的历史与其他人的不同。

同步两个main分支的唯一方法是将它们重新合并在一起,从而产生一个额外的合并提交和两组包含相同更改的提交(原始的,以及来自您rebase的分支的)。 不用说,这是一个非常令人困惑的情况。

所以,在运行 git rebase 之前,总是问自己,“还有其他人在使用这个分支吗?” 如果答案是肯定的,请开始考虑以非破坏性方式进行更改(例如 git revert 命令)。

强制推送

如果你尝试将变基的main分支推送回远程存储库,Git 将阻止这样做,因为它与远程main分支冲突。 但是,我们可以通过传递 --force 标志来强制推送,如下所示:

# 谨慎使用该命令!
$ git push --force

这会覆盖远程主分支来匹配我们存储库中变基的主分支,这会使团队的其他成员感到非常困惑。 因此,只有当我们确切地知道自己在做什么时,才能非常小心地使用此命令。

我们应该强制推送的唯一的可能情况是在将私有feature分支推送到远程存储库(例如,出于备份目的)之后执行本地清理时。 同样,重要的是,没有人从 feature 分支的原始版本执行提交。

除非注明转载,本站文章均为原创或翻译,欢迎转载,转载请以链接形式注明出处

本文地址:

迹忆客

专注技术分享,项目实战分享!

技术宅 乐于分享 7年编程经验
社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

热门文章

教程更新

热门标签

git