Git Rebase
wptr33 2025-05-14 17:10 3 浏览
本文档将深入讨论 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 操作来调查回归的引入时,拥有干净历史的好处就变得切实可见。一个更现实的场景是:
- 在主分支中发现了一个 bug。一个之前正常工作的功能现在出现了问题。
- 由于"干净的历史",开发人员使用 git log 检查主分支的历史,能够快速理解项目的历史。
- 开发人员无法使用 git log 确定 bug 是何时引入的,因此执行了 git bisect。
- 由于 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 丢失的提交
相关推荐
- Git 的设计:版本管理的天才之作
-
Git的设计之所以被称为“天才”,是因为它通过一系列**革命性的理念**和**精妙的工程实现**,完美解决了版本控制中的核心痛点。以下是其设计精髓的深度解析:---###一、**颠覆传统的核心设计...
- IDEA上如何重新设置git账号密码
-
修改git账号密码,使用IDEA拉取项目的文件,出现如下错误信息。fatal:unabletoaccess'http://192.168.105.101:8901/XX/XX-XX-p...
- 在IDEA中利用ignore插件忽略Git非必要提交的文件
-
迎关注我的头条号:Wooola,10年Java软件开发及架构设计经验,专注于Java、Go语言、微服务架构,致力于每天分享原创文章、快乐编码和开源技术。前言在IEDA中,使用Maven建多工程编写代码...
- Git入门系列之分支切换完全指南
-
在Git中切换分支时,若存在未提交的修改,需谨慎处理以避免数据丢失。主要注意事项包括:1)通过gitstatus检查当前修改;2)优先使用gitstash暂存修改再切换;3)可提交修...
- 解决Git推送提交时'src refspec master does not match any'错误
-
技术背景在使用Git进行代码管理时,我们经常会遇到各种问题。其中,“srcrefspecmasterdoesnotmatchany”错误是一个比较常见的问题。当我们尝试使用...
- 修改git提交的用户名
-
在我们项目中,新手同学们往往由于不当操作导致提交的用户名填写错误,当我们用户名填写错误的时候可以通过命令修改。获取当前用户名:gitconfiguser.name...
- 在项目管理中,自动关联Git代码提交,集成Gitlab/码云/Git等
-
不再让开发提交的代码成为“黑洞”在软件开发过程中,会有一个问题和担心,就是不知道开发人员提交的代码质量如何,规范怎样。更为让人痛苦的莫过于当时某个功能需求改了什么代码,根本无人知道。今天,分享一个工具...
- 常用的十五个Git命令汇总?
-
Git是一个分布式的版本管理系统,在开发中被广泛应用于代码版本的管理,下面就是在日常开发中常用的一些Git命令以及其示例操作,如下所示,我们就来一起看看吧!gitinit用于初始化一个新的Git仓库...
- git修改已提交记录的用户信息
-
背景介绍因为使用的是个人电脑,配置的git全局config的用户信息是和github的账户一致的。新下载的工作git,由于没有单独设置局部的用户信息,导致提交记录使用的是github用户,在push代...
- 刚来公司,大佬让我Git下 我该怎么办?
-
我们在开发过程中,都会用到版本控制工具。常用的工具有SVNGIt等。但现在越来越多的人喜欢用Git。本文为你介绍新手如何快速上手Git。创建自己的远程仓库远程仓库,顾名思义。就是将自己的代码放到远程服...
- Git+Maven+Sonar实现提交代码前进行代码的质量检查
-
Git+Maven+Sonar实现提交代码前进行代码的质量检查一、前言为了规范代码质量,使开发人员写出更高质量的代码,实践了一下git-hooks中的pre-commit钩子,可以在提交代码时强制校验...
- Git Rebase
-
本文档将深入讨论gitrebase命令。Rebase命令在设置仓库和重写历史页面中也有涉及。本页将更详细地介绍gitrebase的配置和执行。这里将涵盖常见的Rebase使用场景和注...
- Git提交规范
-
一、分区存储...
- git合并分支时禁止合并特定文件
-
问题:1.在日常开发过程中经常会遇到多环境,但是环境文件不同的情况,导致每次切换git环境时候非常麻烦,可能会提交上来不需要提交的文件,一个文件来回提交修改。场景:...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
因果推断Matching方式实现代码 因果推断模型
-
git pull命令使用实例 git pull--rebase
-
git fetch 和git pull 的异同 git中fetch和pull的区别
-
面试官:git pull是哪两个指令的组合?
-
git pull 和git fetch 命令分别有什么作用?二者有什么区别?
-
git 执行pull错误如何撤销 git pull fail
-
git pull 之后本地代码被覆盖 解决方案
-
还可以这样玩?Git基本原理及各种骚操作,涨知识了
-
git命令之pull git.pull
-
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)