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

Git Rebase

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

本文档将深入讨论 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 丢失的提交

相关推荐

一篇文章带你了解PHP的学习使用(php的教程)

ThinkPHP5实战...

在memcached管理php的session(memcached libevent)

PHP的session(会话管理)一般是以文件形式进行,而在多个Web服务器之间进行session管理时memecached会比文件管理方式更加方便。在这里介绍如何使用memcached管理PHP的s...

php传值和传引用的区别(php 传值和传引用)

php传值:在函数范围内,改变变量值得大小,都不会影响到函数外边的变量值。PHP传引用:在函数范围内,对值的任何改变,在函数外部也有所体现,因为传引用传的是内存地址。传值:和copy是一样的。【打个比...

PHP 常量详解教程(php常量和变量)

常量类似变量,但是常量一旦被定义就无法更改或撤销定义。PHP常量常量是单个值的标识符(名称)。在脚本中无法改变该值。有效的常量名以字符或下划线开头(常量名称前面没有$符号)。注释:与变量不同,常...

php自学零基础入门小知识(php新手入门教程)

我们就把PHP入门当成一个苹果吧!一口一口的吃掉他!不啰嗦了!开始了1、嵌入方法:类似ASP的<%,PHP可以是<?php或者是<?,结束符号是?>,当然您也可以自己指定。2、...

PHP 语法详解(php语法大全)

PHP脚本在服务器上执行,然后向浏览器发送回纯HTML结果。基础PHP语法PHP脚本可放置于文档中的任何位置。PHP脚本以<?php开头,以?>结尾:<?php...

PHP笔记(一)PHP基础知识(php必背知识点)

创建PHP程序PHP代码框架<?php>2.文件命名规则...

PHP 8新特性之Attributes(注解),你掌握了吗?

PHP8的Alpha版本,过几天就要发布了,其中包含了不少的新特性,当然我自己认为最重要的还是JIT,这个我从2013年开始参与,中间挫折无数,失败无数后,终于要发布的东东。不过,今天呢,我不打算谈J...

PHP基本语法之标记与注释(php注释规范)

1、标记由于PHP是嵌入式脚本语言,它在实际开发中经常会与HTML内容混在一起,所以为了区分HTML与PHP代码,需要使用标记对PHP代码进行标识。如:<html>...

php注解(PHP注解 性能)

目标了解和使用php注解,如果你已经掌握其他一种具有注解的语言,例如:java、python等,你在本文中只需要了解点语法就行。示例php8以前的版本,注解写在注释里,如果你掌握其他语言的注解,你是不...

数据丢失?别慌!MySQL备份恢复攻略

想象一下,某个晴朗的午后,你正享受着咖啡,突然接到紧急电话:你的网站或APP彻底挂了!系统崩溃,界面全白。虽然心头一紧,但你或许还能安慰自己:系统崩溃只是暂停服务,数据还在,修复修复就好了。然而,如果...

MySQL 日志:undo log、redo log、binlog

今天来和大家分享MySQL的三个日志文件,可以说MySQL的多数特性都是围绕日志文件实现,而其中最重要的有以下三种:...

MySQL三大日志:binlog、redolog、undolog全解析

binlog概述在MySQL数据库中,binlog可是个相当重要的存在,它的全称为binarylog,也就是二进制日志。它就像是数据库的“记忆本”,记录了所有的DDL(数据定义语言)和...

1、MySQL数据库介绍(mysql数据库简单介绍)

1.1数据库的核心定义数据库的本质数据库乃存储数据对象之容器,涵盖如下关键组件:表(Table)...

MySQL 日志双雄:实时监控与历史归档实战优化

MySQL日志双雄:实时监控+历史归档实战用这招让你家日志系统再也不卡不爆炸MySQL十亿级日志处理:从洪峰到归档全攻略手把手教你用MySQL搞定ELK级日志监控在微服务架构大行其道的今天,日志系统早...