Git 操作补充:cherry-pick、变基
1. 挑选提交合并 git cherry-pick
对于多分支的代码库,将代码从一个分支转移到另一个分支是一种常见的需求,这可以分成两种情况:一种情况是,你需要另一个分支的所有代码变动,那么就采用 git merge;另一种情况是,你只需要部分代码变动(某几个提交),这时可以采用 git cherry-pick,语法为:git cherry-pick <commitHash>,将指定提交合并到另一个分支。
举例来说,假设代码仓库有 master 和 feature 两个分支,提交历史如下,现在将 feture 分支的提交 f 应用到 master 分支。
a - b - c - d Master
\
e - f - g Feature
# 切换到 master 分支
$ git checkout master# Cherry pick 操作
$ git cherry-pick f
上面的操作完成以后,代码库就变成了下面的样子(master 分支的末尾增加了一个提交 f)。
a - b - c - d - f Master
\
e - f - g Feature
# 参数为分支名,表示转移该分支的最新一次提交。
$ git cherry-pick feature# 一次转移多个提交
$ git cherry-pick <HashA> <HashB>
# 上述命令能将 A 和 B 两个提交应用到当前分支,这会在当前分支生成两个对应的新提交。# 转移一系列的连续提交,可以使用下面的简便语法
$ git cherry-pick A..B
# 上述命令将转移从 A 到 B (不包括A)的所有提交,A、B的顺序一定要正确:提交 A 必须早于提交 B,否则命令将失败,但不会报错。# 转移从 A 到 B (包括A)的所有提交
$ git cherry-pick A^..B
2. 变基 git rebase
在 Git 中,整合来自不同分支的修改,除了 merge,还有一种方法,变基 rebase。git rebase 命令基本是一个自动化的 cherry-pick 命令,它计算出一系列的提交,然后在其地方以同样的顺序一个一个的 cherry-pick 它们。
Git 中有一些修改会覆盖提交历史,列举如下,在使用这些命令时,需要谨慎操作,以免不小心覆盖提交历史,导致代码丢失或者出现其他问题。
- 使用 git commit --amend 命令修改最近一次提交的信息,会覆盖最近一次提交的记录。
- 使用 git rebase 命令修改提交记录,这会修改提交的 SHA-1 校验和,覆盖提交历史。
- 使用 git reset 命令回滚到之前的提交,这会删除之后的提交历史。
- 使用 git push --force 命令强制推送修改,这会覆盖远程分支的提交历史。
2.1 Case 1:git rebase <upstream>
假设在一个项目开发过程中,分叉到两个不同分支,每个分支都提交了更新。
可以使用 merge 命令整合分支,它会把两个分支的最新快照(C3 和 C4)以及二者最近的共同祖先(C2)进行三方合并,合并的结果是生成一个新的快照(并提交)。
还有一种方法:使用变基 git rebase 整合分支,git rebase 的语法可以简写为:git rebase [--onto <newbase>] [<upstream> [<branch>]],表示将 <branch> 分支从 <upstream> 开始的提交应用到 <newbase> 分支上。具体来说,它会将 <branch> 分支自 <upstream> 之后的提交移动到 <newbase> 分支的最新提交之后,使得 <branch> 分支的提交历史看起来像是在 <newbase>分支的基础上进行的。
可以省略的参数是 <newbase> 和 <branch>;如果省略 --onto 参数,将以 <upstream> 参数指定的分支作为基底进行变基操作。也就是说,将当前所在分支(HEAD 指向的分支)与 <upstream> 参数指定的分支之间的差异应用到 <upstream>分支上;如果省略 <branch>,将把当前所在分支,即 HEAD 指向的分支,作为 <branch> 参数传递给 git rebase 命令。
$ git checkout experiment$ git rebase master
接下来运行 git checkout master 回到 master 分支,然后运行 git merge experiment 进行一次快进合并。C4' 指向的快照就和使用 merge 得到的 C5 指向的快照一模一样,这两种整合方法的最终 结果没有任何区别,但是变基使得提交历史更加整洁。 你在查看一个经过变基的分支的历史记录时会发现,尽管实际的开发工作是并行的,但它们看上去就像是串行的一样,提交历史是一条直线没有分叉。
一般这样做的目的是为了确保在向远程分支推送时能保持提交历史的整洁,例如向某个其他人维护的项目贡献代码时。在这种情况下,你首先在自己的分支里进行开发,当开发完成时你需要先将你的代码变基到 origin/master 上,然后再向主项目提交修改。这样的话,该项目的维护者就不再需要进行整合工作,只需要快进合并便可。
2.2 Case2:git rebase [--onto <newbase>] [<upstream> [<branch>]]
假设你的项目提交历史如下:你创建了一个特性分支 server,为服务端添加了一些功能,提交了 C3 和 C4。然后从 C3 上创建了特性分支 client,为客户端添加 了一些功能,提交了 C8 和 C9。 最后,你回到 server 分支,又提交了 C10。
你希望将 client 中的修改合并到 master 主分支并发布,但暂时并不想合并 server 中的修改,因为它们还需要经过更全面的测试。这时,你可以使用 git rebase 命令的 --onto 选项,选择在 client 分支里但不在 server 分支里的修改(即 C8 和 C9),将它们应用在 master 分支上。
运行命令:git rebase --onto master server client,其含义是:“取出 client 分支,找出处于 client 分支和 server 分支的共同祖先之后的修改,然后把它们在 master 分支上重放一遍”。然后将 client 合并到 master。
$ git rebase --onto master server client
$ git checkout master
$ git merge client
$ git rebase master server
$ git checkout master
$ git merge server$ git branch -d client
$ git branch -d server
2.3 Case3:变基使用不当的风险
警告:不要对仓库外有副本的分支执行变基。如果你遵循这条金科玉律,就不会出差错。 否则,人民群众会仇恨你,你的朋友和家人也会嘲笑你,唾弃你。-- Scott Chacon
只要你把变基命令当作是在推送前清理提交使之整洁的工具,并且只在从未推送至共用仓库的提交上执行变基命令,就不会有事。 假如在那些已经被推送至公用仓库的提交上,执行变基命令,并因此丢弃了一些别人的开发所基于的提交,那你就有大麻烦了,你的同事也会因此鄙视你。
2.3.1 变基使用不当的例子
假设你从一个中央服务器克隆然后在它的基础上进行了一些开发,提交历史如图所示:
一段时间后,其他项目成员向中央服务器提交了一些修改,其中包括一次合并。
你抓取了这些在远程分支上的修改,并将其合并到你本地的开发分支,你的提交历史如下:
接下来,这个成员又决定把合并操作回滚,改用变基,并用 git push --force 命令强制推送修改,这会覆盖远程分支的提交历史。
此时,你从服务器抓取更新,会发现多出来一些新的提交。如果你执行 git pull 命令,你将合并来自两条提交历史的内容,生成一个新的合并提交 C8。
此时,如果你执行 git log 命令,你会发现有两个提交的作者、日期、日志居然是一样的,这会令人感到混乱。 此外,如果你将这一堆又推送到服务器上,实际上是将那些已经被变基抛弃的提交又找了回来,这会令人感到更加混乱。很明显对方并不想在提交历史中看到 C4 和 C6,因为之前就是他把这两个提交通过变基丢弃的。
2.3.2 解决方法
如果团队中的某人强制推送并覆盖了一些你所基于的提交,你需要做的就是检查你做了哪些修改,以及他们覆盖了哪些修改。
方案1:git fetch + git rebase:在一个被变基然后强制推送的分支上再次执行变基
对于这种,有人推送了经过变基的提交,并丢弃了你的本地开发所基于的一些提交,不要使用 git pull,而是先 git fetch,再执行 git rebase teamone/master, Git 将会:
- 检查哪些提交是我们的分支上独有的(C2,C3,C4,C6,C7)
- 检查其中哪些提交不是合并操作的结果(C2,C3,C4)
- 检查哪些提交在对方覆盖更新时并没有被纳入目标分支(C2 和 C3,C4 其实就是 C4')
- 把查到的这些提交应用在 teamone/master 上面
想要上述方案有效,还需要对方在变基时确保 C4' 和 C4 是几乎一样的。 否则变基操作将无法识别,并新建另一个类似 C4 的补丁(而这个补丁很可能无法整洁的整合入历史,因为补丁中的修改已经存在于某个地方了)。
方案2:使用 git pull --rebase 而不是直接用 git pull
如果你或你的同事在某些情形下,不得不强制推送经过变基的提交,请一定要通知每个人执行 git pull --rebase 命令,这样尽管不能避免麻烦,但能有所缓解。
相关文章:

Git 操作补充:cherry-pick、变基
1. 挑选提交合并 git cherry-pick 对于多分支的代码库,将代码从一个分支转移到另一个分支是一种常见的需求,这可以分成两种情况:一种情况是,你需要另一个分支的所有代码变动,那么就采用 git merge;另一种情…...

在 PostgreSQL 中,如何处理大规模的文本数据以提高查询性能?
文章目录 一、引言二、理解 PostgreSQL 中的文本数据类型三、数据建模策略四、索引选择与优化五、查询优化技巧六、示例场景与性能对比七、分区表八、数据压缩九、定期维护十、总结 在 PostgreSQL 中处理大规模文本数据以提高查询性能 一、引言 在当今的数据驱动的世界中&…...

秋招提前批面试经验分享(下)
⭐️感谢点开文章👋,欢迎来到我的微信公众号!我是恒心😊 一位热爱技术分享的博主。如果觉得本文能帮到您,劳烦点个赞、在看支持一下哈👍! ⭐️我叫恒心,一名喜欢书写博客的研究生在读…...

零基础STM32单片机编程入门(七)定时器PWM波输出实战含源码视频
文章目录 一.概要二.PWM产生框架图三.CubeMX配置一个TIME输出1KHZ,占空比50%PWM波例程1.硬件准备2.创建工程3.测量波形结果 四.CubeMX工程源代码下载五.讲解视频链接地址六.小结 一.概要 脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写&…...

【ubuntu自启shell脚本】——在ubuntu中如何使用系统自带的启动应用程序设置开机自启自己的本地shell脚本
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、设置开机自启shell脚本1.使用 gnome-session-properties2.测试的shell例程代码 总结 前言 在Ubuntu系统中设置开机自启脚本是一种重要的自动化方法。开机自…...
nodejs配置国内镜像
# 设置淘宝镜像 npm config set registry https://registry.npmmirror.com# 查看镜像源 npm get registry...

【JavaEE】多线程进阶
🤡🤡🤡个人主页🤡🤡🤡 🤡🤡🤡JavaEE专栏🤡🤡🤡 文章目录 1.锁策略1.1悲观锁和乐观锁1.2重量级锁和轻量级锁1.3自旋锁和挂起等待锁1.4可…...
大模型LLM面试常见算法题-包括Attention和Transformer常见面试题
大模型: 位置编码有哪些? 介绍LoRA与QLoRA RAG和微调的区别是什么? 哪些因素会导致LLM的偏见? 什么是思维链(CoT)提示? Tokenizer的实现方法及原理 解释一下大模型的涌现能力?…...

90元搭建渗透/攻防利器盒子!【硬件篇】
前言 以下内容请自行思考后进行实践。 使用场景 在某些情况下开软件进行IP代理很麻烦,并不能实现真正全局,而且还老容易忘记,那么为了在实景工作中,防止蓝队猴子封IP,此文正现。 正文 先说一下实验效果࿱…...

用vue2+elementUI封装手机端选择器picker组件,支持单选、多选、远程搜索多选
单选注意点: touchmove.prevent: 在 touchmove 事件上添加 .prevent 修饰符,以阻止默认的滚动行为。 handleTouchStart: 记录触摸开始的 Y 坐标和当前的 translateY 值。 handleTouchMove: 计算触摸移动的距离,并更新 translateY 值。 han…...

『古籍自有答案』古风H5案例赏析
「古籍自有答案」,一部由新京报与字节跳动公益联合打造的古风H5,以诗意盎然的开篇引领用户穿梭于千年文脉。 part1. 创意定位 "人生有惑问先贤,先贤答案存古籍",在这里,每一个灵魂的探问,都能在…...
Laravel模型事件完全指南:触发应用程序的动态行为
标题:Laravel模型事件完全指南:触发应用程序的动态行为 在Laravel框架中,模型事件提供了一种优雅的方式来处理Eloquent模型生命周期中的各种关键时刻。通过监听和响应这些事件,开发者可以自动化许多常见的任务,如日志…...
hot100 |八、二叉树
1-leetcode94. 二叉树的中序遍历 注意:√ 递归方法已经很熟练了,两种不同的递归方式迭代法需要注意,zrm就遇到了要求迭代实现,前序遍历和后续遍历其实不难,中序遍历用的少,注意看一看 // 1.递归方法1Lis…...

Matlab协方差矩阵分解法生成随机场
Matlab协方差矩阵分解法生成随机场 相关系数矩阵 % function outcohesion(x,y,mu,theta) % end % xyload(F:\Research-OUC\基于机器许学习模型的海底斜坡可靠度研究\基于comsol的斜坡稳定性分析\comsol网格操作\grid_operate-matlab.mphtxt); % xxy(:,1); % yxy(:,2); Xlinspac…...
android 在清单文件中配置receiver,系统是何时会注册此广播接收者的?
在 Android 中,通过清单文件(AndroidManifest.xml)配置的广播接收器(BroadcastReceiver),系统会在特定的时机自动注册这些广播接收器。以下是详细的说明: 静态注册的广播接收器 静态注册的广播…...
嵌入式硬件电路常用设计软件
目录 1. Cadence Allegro 2. PADS 3. Altium Designer 4. Multisim 5. Protues 1. Cadence Allegro 功能: Cadence Allegro是Cadence公司推出的先进PCB(Printed Circuit Board,印刷电路板)设计布线工具,也是目前…...
c#的List<T>的SelectMany 和Select
在C#中,List<T>(以及任何实现了IEnumerable<T>的集合)的Select和SelectMany扩展方法都是LINQ(Language Integrated Query)的一部分,用于对集合中的元素进行查询和转换。 尽管它们的作用有些相…...

69.WEB渗透测试-信息收集- WAF、框架组件识别(9)
免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 内容参考于: 易锦网校会员专享课 上一个内容:68.WEB渗透测试-信息收集- WAF、框架组件识别(8) 有无waf存在&am…...

ASCII码对照表(Matplotlib颜色对照表)
文章目录 1、简介1.1 颜色代码 2、Matplotlib库简介2.1 简介2.2 安装2.3 后端2.4 入门例子 3、Matplotlib库颜色3.1 概述3.2 颜色图的分类3.3 颜色格式表示3.4 内置颜色映射3.5 xkcd 颜色映射3.6 颜色命名表 4、Colorcet库5、颜色对照表结语 1、简介 1.1 颜色代码 颜色代码是…...

Mysql-常用函数及其用法总结
1、字符串函数 测试用例如下: 1.1 CONCAT() 将多个字符串连接成一个字符串。 SELECT CONCAT(first_name, , last_name) AS full_name FROM users; -- 期望结果:John Doe, Jane Smith, Michael Johnson 1.2 SUBSTRING() 提取子字符串 SELECT SUBSTR…...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...

c++第七天 继承与派生2
这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分:派生类构造函数与析构函数 当创建一个派生类对象时,基类成员是如何初始化的? 1.当派生类对象创建的时候,基类成员的初始化顺序 …...