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…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...

【深度学习新浪潮】什么是credit assignment problem?
Credit Assignment Problem(信用分配问题) 是机器学习,尤其是强化学习(RL)中的核心挑战之一,指的是如何将最终的奖励或惩罚准确地分配给导致该结果的各个中间动作或决策。在序列决策任务中,智能体执行一系列动作后获得一个最终奖励,但每个动作对最终结果的贡献程度往往…...
React从基础入门到高级实战:React 实战项目 - 项目五:微前端与模块化架构
React 实战项目:微前端与模块化架构 欢迎来到 React 开发教程专栏 的第 30 篇!在前 29 篇文章中,我们从 React 的基础概念逐步深入到高级技巧,涵盖了组件设计、状态管理、路由配置、性能优化和企业级应用等核心内容。这一次&…...