百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

Git Rebase

wptr33 2025-05-14 17:10 45 浏览

本文档将深入讨论 git rebase 命令。Rebase 命令在设置仓库和重写历史页面中也有涉及。本页将更详细地介绍 git rebase 的配置和执行。这里将涵盖常见的 Rebase 使用场景和注意事项。


Rebase 是 Git 中专门用于将一个分支的更改集成到另一个分支的两个工具之一。另一个更改集成工具是 git merge。Merge 始终是一个向前移动的更改记录。而 rebase 则具有强大的历史重写功能。要详细了解 Merge 与 Rebase 的区别,请访问我们的 Merge vs Rebase 指南。Rebase 本身有两种主要模式:"手动"模式和"交互"模式。我们将在下面详细介绍不同的 Rebase 模式。


什么是 git rebase?


Rebasing 是将一系列提交移动或合并到新的基础提交的过程。Rebasing 在特性分支工作流中最有用且最容易可视化。一般过程可以如下所示:

从内容角度来看,rebase 是将分支的基础从一个提交更改为另一个提交,使其看起来像是从不同的提交创建了分支。在内部,Git 通过创建新的提交并将它们应用到指定的基础来实现这一点。重要的是要理解,即使分支看起来相同,它也是由全新的提交组成的。


使用方法


Rebase 的主要原因是保持项目历史的线性。例如,考虑这样一种情况:自从你开始处理特性分支以来,主分支已经有所进展。你希望将主分支的最新更新获取到你的特性分支中,但你想保持分支历史的整洁,使其看起来像是你一直在最新的主分支上工作。这为以后将特性分支干净地合并回主分支提供了好处。为什么我们要保持"干净的历史"?当执行 Git 操作来调查回归的引入时,拥有干净历史的好处就变得切实可见。一个更现实的场景是:

  1. 在主分支中发现了一个 bug。一个之前正常工作的功能现在出现了问题。
  2. 由于"干净的历史",开发人员使用 git log 检查主分支的历史,能够快速理解项目的历史。
  3. 开发人员无法使用 git log 确定 bug 是何时引入的,因此执行了 git bisect。
  4. 由于 Git 历史是干净的,git bisect 在寻找回归时有更精确的提交集可以比较。开发人员很快找到了引入 bug 的提交,并能够采取相应措施。


你有两种选择将特性集成到主分支:直接合并或先 rebase 再合并。前一种选择会导致三方合并和合并提交,而后一种选择会导致快进合并和完美的线性历史。下图展示了如何通过 rebase 到主分支来促进快进合并。

Rebase 是将上游更改集成到本地仓库的常用方法。使用 Git merge 拉取上游更改会导致每次你想查看项目进展时都会产生多余的合并提交。另一方面,rebase 就像是说:"我想基于其他人已经完成的工作来应用我的更改。"


不要 rebase 公共历史


正如我们之前在重写历史中讨论的那样,一旦提交被推送到公共仓库,就永远不应该 rebase 这些提交。Rebase 会用新的提交替换旧的提交,看起来就像是项目历史的那部分突然消失了。


Git rebase 标准模式 vs Git rebase 交互模式


Git rebase 交互模式是当 git rebase 接受 -i 参数时。这代表"交互式"。没有任何参数时,命令以标准模式运行。在这两种情况下,假设我们已经创建了一个单独的特性分支。


# 基于主分支创建特性分支
git checkout -b feature_branch main
# 编辑文件
git commit -a -m "添加新特性"


标准模式下的 Git rebase 会自动获取当前工作分支中的提交,并将它们应用到传递的分支的头部。


git rebase <base>


这会自动将当前分支 rebase 到 <base> 上,<base> 可以是任何类型的提交引用(例如 ID、分支名称、标签或 HEAD 的相对引用)。


使用 -i 标志运行 git rebase 会开始一个交互式 rebase 会话。与盲目移动所有提交到新基础不同,交互式 rebase 让你有机会在过程中修改单个提交。这让你可以通过删除、分割和修改现有的一系列提交来清理历史。这就像是 git commit --amend 的加强版。


git rebase --interactive <base>


这会将当前分支 rebase 到 <base> 上,但使用交互式 rebase 会话。这会打开一个编辑器,你可以在其中为每个要 rebase 的提交输入命令(如下所述)。这些命令决定了单个提交将如何转移到新基础。你还可以重新排序提交列表来更改提交本身的顺序。一旦你为 rebase 中的每个提交指定了命令,Git 将开始播放提交,应用 rebase 命令。rebase 编辑命令如下:


pick 2231360 一些旧的提交
pick ee2adc2 添加新特性

# Rebase 2cf755d..ee2adc2 onto 2cf755d (9 个命令)
#
# 命令:
# p, pick = 使用提交
# r, reword = 使用提交,但编辑提交消息
# e, edit = 使用提交,但停止以进行修改
# s, squash = 使用提交,但合并到前一个提交中
# f, fixup = 类似于 "squash",但丢弃此提交的日志消息
# x, exec = 使用 shell 运行命令(行的其余部分)
# d, drop = 删除提交


额外的 rebase 命令


正如重写历史页面中详细说明的那样,rebase 可用于更改较旧和多个提交、已提交的文件和多个消息。虽然这些是最常见的应用,但 git rebase 还有一些额外的命令选项,在更复杂的应用中可能很有用。


  • git rebase --d 意味着在播放过程中,提交将从最终组合的提交块中丢弃。
  • git rebase --p 保持提交不变。它不会修改提交的消息或内容,并且仍然是分支历史中的单个提交。
  • git rebase --x 在播放过程中在每个标记的提交上执行命令行 shell 脚本。一个有用的例子是在特定提交上运行代码库的测试套件,这可能有助于在 rebase 期间识别回归。


总结


交互式 rebase 让你完全控制项目历史的外观。这为开发人员提供了很大的自由,因为它允许他们在专注于编写代码时提交"混乱"的历史,然后在事后清理。


大多数开发人员喜欢在将特性分支合并到主代码库之前使用交互式 rebase 来完善它。这让他们有机会压缩不重要的提交,删除过时的提交,并确保在提交到"官方"项目历史之前一切都井然有序。对其他人来说,看起来整个特性是在一系列精心策划的提交中开发的。


交互式 rebase 的真正威力可以在结果主分支的历史中看到。对其他人来说,看起来你是一个出色的开发人员,第一次就完美地实现了新特性。这就是交互式 rebase 如何保持项目历史的整洁和有意义。


配置选项


有一些 rebase 属性可以使用 git config 设置。这些选项将改变 git rebase 输出的外观和感觉。


  • rebase.stat:一个布尔值,默认为 false。该选项切换显示自上次 rebase 以来更改的视觉 diffstat 内容。
  • rebase.autoSquash:一个布尔值,用于切换 --autosquash 行为。
  • rebase.missingCommitsCheck:可以设置为多个值,这些值会改变 rebase 在缺失提交周围的行为:
  • warn:在交互模式下打印警告输出,警告已删除的提交
  • error:停止 rebase 并打印已删除提交的警告消息
  • ignore:默认设置,忽略任何缺失提交警告
  • rebase.instructionFormat:一个 git log 格式字符串,用于格式化交互式 rebase 显示


高级 rebase 应用


命令行参数 --onto 可以传递给 git rebase。在 git rebase --onto 模式下,命令扩展为:


git rebase --onto <newbase> <oldbase>


--onto 命令启用了一种更强大的 rebase 形式,允许传递特定的引用作为 rebase 的尖端。假设我们有一个示例仓库,分支如下:


   o---o---o---o---o  main
        \
         o---o---o---o---o  featureA
              \
               o---o---o  featureB


featureB 基于 featureA,然而,我们意识到 featureB 不依赖于 featureA 的任何更改,可以直接从 main 分支出来。


git rebase --onto main featureA featureB


featureA 是 <oldbase>。main 成为 <newbase>,featureB 是 <newbase> 的 HEAD 指向的引用。结果如下:


                      o---o---o  featureB
                     /
    o---o---o---o---o  main
     \
      o---o---o---o---o  featureA


理解 rebase 的危险


在使用 Git Rebase 时需要考虑的一个警告是,在 rebase 工作流中合并冲突可能会更频繁地发生。如果你有一个长期存在的分支与主分支偏离,就会发生这种情况。最终你会想要对主分支进行 rebase,那时它可能包含许多新的提交,你的分支更改可能会与之冲突。通过频繁地对主分支进行 rebase 和更频繁地提交,这很容易解决。--continue 和 --abort 命令行参数可以传递给 git rebase,以在处理冲突时推进或重置 rebase。


一个更严重的 rebase 警告是交互式历史重写中丢失的提交。在交互模式下运行 rebase 并执行 squash 或 drop 等子命令会从分支的立即日志中删除提交。乍一看,这似乎像是提交永久消失了。使用 git reflog 可以恢复这些提交,并且可以撤销整个 rebase。有关使用 git reflog 查找丢失提交的更多信息,请访问我们的 Git reflog 文档页面。


Git Rebase 本身并不严重危险。真正的危险情况出现在执行历史重写交互式 rebase 并将结果强制推送到其他用户共享的远程分支时。应该避免这种模式,因为它有可能在用户拉取时覆盖其他远程用户的工作。


从上游 rebase 中恢复


如果另一个用户已经 rebase 并强制推送到你正在提交的分支,git pull 将用强制推送的尖端覆盖你基于该先前分支的任何提交。幸运的是,使用 git reflog 你可以获取远程分支的 reflog。在远程分支的 reflog 中,你可以找到它被 rebase 之前的引用。然后你可以使用 --onto 选项将你的分支 rebase 到该远程应用上,如上面高级 Rebase 应用部分所述。


总结


在本文中,我们介绍了 git rebase 的用法。我们讨论了基本和高级用例以及更高级的示例。一些关键的讨论点是:


  • git rebase 标准模式与交互模式
  • git rebase 配置选项
  • git rebase --onto
  • git rebase 丢失的提交

相关推荐

oracle数据导入导出_oracle数据导入导出工具

关于oracle的数据导入导出,这个功能的使用场景,一般是换服务环境,把原先的oracle数据导入到另外一台oracle数据库,或者导出备份使用。只不过oracle的导入导出命令不好记忆,稍稍有点复杂...

继续学习Python中的while true/break语句

上次讲到if语句的用法,大家在微信公众号问了小编很多问题,那么小编在这几种解决一下,1.else和elif是子模块,不能单独使用2.一个if语句中可以包括很多个elif语句,但结尾只能有一个else解...

python continue和break的区别_python中break语句和continue语句的区别

python中循环语句经常会使用continue和break,那么这2者的区别是?continue是跳出本次循环,进行下一次循环;break是跳出整个循环;例如:...

简单学Python——关键字6——break和continue

Python退出循环,有break语句和continue语句两种实现方式。break语句和continue语句的区别:break语句作用是终止循环。continue语句作用是跳出本轮循环,继续下一次循...

2-1,0基础学Python之 break退出循环、 continue继续循环 多重循

用for循环或者while循环时,如果要在循环体内直接退出循环,可以使用break语句。比如计算1至100的整数和,我们用while来实现:sum=0x=1whileTrue...

Python 中 break 和 continue 傻傻分不清

大家好啊,我是大田。今天分享一下break和continue在代码中的执行效果是什么,进一步区分出二者的区别。一、continue例1:当小明3岁时不打印年龄,其余年龄正常循环打印。可以看...

python中的流程控制语句:continue、break 和 return使用方法

Python中,continue、break和return是控制流程的关键语句,用于在循环或函数中提前退出或跳过某些操作。它们的用途和区别如下:1.continue(跳过当前循环的剩余部分,进...

L017:continue和break - 教程文案

continue和break在Python中,continue和break是用于控制循环(如for和while)执行流程的关键字,它们的作用如下:1.continue:跳过当前迭代,...

作为前端开发者,你都经历过怎样的面试?

已经裸辞1个月了,最近开始投简历找工作,遇到各种各样的面试,今天分享一下。其实在职的时候也做过面试官,面试官时,感觉自己问的问题很难区分候选人的能力,最好的办法就是看看候选人的github上的代码仓库...

面试被问 const 是否不可变?这样回答才显功底

作为前端开发者,我在学习ES6特性时,总被const的"善变"搞得一头雾水——为什么用const声明的数组还能push元素?为什么基本类型赋值就会报错?直到翻遍MDN文档、对着内存图反...

2023金九银十必看前端面试题!2w字精品!

导文2023金九银十必看前端面试题!金九银十黄金期来了想要跳槽的小伙伴快来看啊CSS1.请解释CSS的盒模型是什么,并描述其组成部分。答案:CSS的盒模型是用于布局和定位元素的概念。它由内容区域...

前端面试总结_前端面试题整理

记得当时大二的时候,看到实验室的学长学姐忙于各种春招,有些收获了大厂offer,有些还在苦苦面试,其实那时候的心里还蛮忐忑的,不知道自己大三的时候会是什么样的一个水平,所以从19年的寒假放完,大二下学...

由浅入深,66条JavaScript面试知识点(七)

作者:JakeZhang转发链接:https://juejin.im/post/5ef8377f6fb9a07e693a6061目录由浅入深,66条JavaScript面试知识点(一)由浅入深,66...

2024前端面试真题之—VUE篇_前端面试题vue2020及答案

添加图片注释,不超过140字(可选)1.vue的生命周期有哪些及每个生命周期做了什么?beforeCreate是newVue()之后触发的第一个钩子,在当前阶段data、methods、com...

今年最常见的前端面试题,你会做几道?

在面试或招聘前端开发人员时,期望、现实和需求之间总是存在着巨大差距。面试其实是一个交流想法的地方,挑战人们的思考方式,并客观地分析给定的问题。可以通过面试了解人们如何做出决策,了解一个人对技术和解决问...