Git 操作补充:cherry-pick、变基

1. 挑选提交合并 git cherry-pick

对于多分支的代码库,将代码从一个分支转移到另一个分支是一种常见的需求,这可以分成两种情况:一种情况是,你需要另一个分支的所有代码变动,那么就采用 git merge;另一种情况是,你只需要部分代码变动(某几个提交),这时可以采用 git cherry-pick,语法为:git cherry-pick <commitHash>,将指定提交合并到另一个分支。

2f4a81027087445aa0fc72902e651f1e.png

举例来说,假设代码仓库有 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

ec5676717d4a44fb9d7ef120f5eece5a.png

f20365bb4c9742039291e7948f4d5b20.png

2. 变基 git rebase

在 Git 中,整合来自不同分支的修改,除了 merge,还有一种方法,变基 rebase。git rebase 命令基本是一个自动化的 cherry-pick 命令,它计算出一系列的提交,然后在其地方以同样的顺序一个一个的 cherry-pick 它们。

Git 中有一些修改会覆盖提交历史,列举如下,在使用这些命令时,需要谨慎操作,以免不小心覆盖提交历史,导致代码丢失或者出现其他问题。

  1. 使用 git commit --amend 命令修改最近一次提交的信息,会覆盖最近一次提交的记录。
  2. 使用 git rebase 命令修改提交记录,这会修改提交的 SHA-1 校验和,覆盖提交历史。
  3. 使用 git reset 命令回滚到之前的提交,这会删除之后的提交历史。
  4. 使用 git push --force 命令强制推送修改,这会覆盖远程分支的提交历史。

2.1 Case 1:git rebase <upstream> 

假设在一个项目开发过程中,分叉到两个不同分支,每个分支都提交了更新。

221a800f41d94e82ba3e96cf4b49dc24.png

可以使用 merge 命令整合分支,它会把两个分支的最新快照(C3 和 C4)以及二者最近的共同祖先(C2)进行三方合并,合并的结果是生成一个新的快照(并提交)。

8112f27713554289a3e0e665db65d4a6.png

还有一种方法:使用变基 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 命令。

a253d049fccf40d29a1ab83d925b7d72.png

 eecfdff7d6e74857841bdab01e03dc9c.png

cd0ef0e94dc54f628a7dac0ced001776.png

$ git checkout experiment

$ git rebase master

cae1c32f1ad64e5790312c8e47d06196.png

接下来运行 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。

 

fce3bb3187aa4e1abf4fee7e11a054c0.png

你希望将 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

96e938c7a0dc427382c2b6605d8dd16b.png

a236b007a71844b78bafeed4cbfadf28.png

f7fae58aca3b499eaecc6ab0bee289ea.png

cbb969796b774ecfb0663ab1fec376f9.png

2.3 Case3:变基使用不当的风险

警告:不要对仓库外有副本的分支执行变基。如果你遵循这条金科玉律,就不会出差错。 否则,人民群众会仇恨你,你的朋友和家人也会嘲笑你,唾弃你。-- Scott Chacon

只要你把变基命令当作是在推送前清理提交使之整洁的工具,并且只在从未推送至共用仓库的提交上执行变基命令,就不会有事。 假如在那些已经被推送至公用仓库的提交上,执行变基命令,并因此丢弃了一些别人的开发所基于的提交,那你就有大麻烦了,你的同事也会因此鄙视你。

2.3.1 变基使用不当的例子

假设你从一个中央服务器克隆然后在它的基础上进行了一些开发,提交历史如图所示:

cd8fe74a24ee45db86e0de3c8cd1c722.png

一段时间后,其他项目成员向中央服务器提交了一些修改,其中包括一次合并。 

fa280b6e7b0a4175a54ea83fb7e8ee2d.png

你抓取了这些在远程分支上的修改,并将其合并到你本地的开发分支,你的提交历史如下:

b2e13ae3c22c44198d9ebcadccf9bfd4.png

接下来,这个成员又决定把合并操作回滚,改用变基,并用 git push --force 命令强制推送修改,这会覆盖远程分支的提交历史。

ff017e3d657147bea6979bd5ddab87ad.png

此时,你从服务器抓取更新,会发现多出来一些新的提交。如果你执行 git pull 命令,你将合并来自两条提交历史的内容,生成一个新的合并提交 C8。

5bca425180ad49f79af227deef5bcae7.png

此时,如果你执行 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 的补丁(而这个补丁很可能无法整洁的整合入历史,因为补丁中的修改已经存在于某个地方了)。

2b20418f71984ad3a9f8d0dead792d9d.png方案2:使用 git pull --rebase 而不是直接用 git pull

如果你或你的同事在某些情形下,不得不强制推送经过变基的提交,请一定要通知每个人执行 git pull --rebase 命令,这样尽管不能避免麻烦,但能有所缓解。

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/782146.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Unity2D 2022:UI】制作角色血条

一、创建血底UI 1. 创建画布&#xff08;Canvas&#xff09; 2. 在画布上添加血底图像&#xff08;Image&#xff09;子物体 二、编辑血底UI 1. 将血底图片拖入源图像&#xff08;Source Image&#xff09;中 2. 点击设置为图片的原大小&#xff08;Set Native Size&#x…

算法重新刷题

基础算法 前缀和 一维前缀和 [USACO16JAN] Subsequences Summing to Sevens S - 洛谷 这一题主要是需要结合数学知识来求解&#xff0c; #include <iostream> #include <cstring> #include <cstdio> #include <algorithm>using namespace std;con…

java花店管理系统eclipse开发mysql数据库

1 绪论 1.1 系统开发目的 随着人们物质生活水平和经济水平的不断提高&#xff0c;室内绿化布置、家庭园艺装饰、礼仪鲜花等日益受到重视和青睐&#xff0c;以及送鲜花给亲朋好友来表达自己的情谊。传统的花店对于信息的管理的主要方式是基于文本、表格等纸质手工处理&#xf…

【经验篇】Spring Data JPA开启批量更新时乐观锁失效问题

乐观锁机制 什么是乐观锁&#xff1f; 乐观锁的基本思想是&#xff0c;认为在大多数情况下&#xff0c;数据访问不会导致冲突。因此&#xff0c;乐观锁允许多个事务同时读取和修改相同的数据&#xff0c;而不进行显式的锁定。在提交事务之前&#xff0c;会检查是否有其他事务…

mac M1安装 VSCode

最近在学黑马程序员Java最新AI若依框架项目开发&#xff0c;里面前端用的是Visual Studio Code 所以我也就下载安装了一下&#xff0c;系统是M1芯片的&#xff0c;安装过程还是有点坑的写下来大家注意一下 1.在appstore中下载 2.在系统终端中输入 clang 显示如下图 那么在终端输…

【Linux进程】命令行参数 环境变量(详解)

目录 前言 1. 命令行参数 什么是命令行参数? 2. 环境变量 常见的环境变量 如何修改环境变量? 获取环境变量 环境变量的组织方式 拓展问题 导入环境变量 3. 本地变量* 总结 前言 在使用Linux指令的时候, 都是指令后边根命令行参数, 每个指令本质都是一个一个的可执行程…

JAVA集合框架、CAS、AQS

目录 一、java 的集合框架有哪些? 二、说-下 ArrayList 和 LinkedList? 三、HashSet和TreeSet的区别? 四、HashMap 的数据结构是什么? 五、CAS机制 六、AQS理解 一、java 的集合框架有哪些? Collection 是 Java 集合框架中的一个根接口&#xff0c;位于 java.util 包中。它…

亲密数对C++函数

自定义函数 #include<bits/stdc.h> using namespace std; //求n的因子和自定义函数 int yinzihe(int n){//使用2~sqrt(n)成对求解因子和int r0,i;//变量 r 初始值为0&#xff0c;因为要存放因子和for(i2;i<sqrt(n);i) {//回顾sqrt()课程//如果 i 是 n 的因子&#xf…

微笑背后的秘密:理解自闭症儿童的面部表情控制

在星贝育园自闭症儿童康复学校&#xff0c;我们常常遇到家长们提出的一个有趣而引人深思的问题&#xff1a;“为什么我的孩子似乎控制不住面部表情&#xff0c;尤其是频繁地笑&#xff1f;”这个问题背后&#xff0c;隐藏着自闭症谱系障碍&#xff08;ASD&#xff09;儿童独特的…

Caffeinated for Mac v2.0.6 Mac防休眠应用 兼容 M1/M2/M3

Caffeinated 可以防止您的 Mac 进入休眠状态、屏幕变暗或者启动屏幕保护。 应用介绍 您的屏幕是否总是在您不希望的时候变暗&#xff1f;那么Caffeinated就是您解决这个大麻烦的最好工具啦。Caffeinated是在Caffeine这个非常便捷、有用的工具的基础上开发而来的。Caffeinated…

20240707 每日AI必读资讯

&#x1f9e0;中国生成式AI专利数量超过美国 6 倍 - 中国在2014年至2023年期间申请的生成式AI专利数量达到38210个&#xff0c;超过了美国的6倍。 - 腾讯、平安保险集团和百度是GenAI专利数量最多的中国公司。 - 中国的顶级学术机构和技术生态为生成式AI的发展提供了强大支持…

算法简介:什么是算法?——定义、历史与应用详解

引言 在现代计算机科学中&#xff0c;算法是一个核心概念。无论是编程还是数据分析&#xff0c;算法都扮演着至关重要的角色。在这篇博客中&#xff0c;我们将深入探讨算法的定义、历史背景以及它在计算机科学中的地位和实际应用。 什么是算法&#xff1f; 算法是解决特定问题…

DHCP的原理及配置

目录 一、了解DHCP服务 1.什么是DHCP 1.1DHCP广播 2.使用DHCP的好处 2.1为什么使用DHCP 3.DHCP的模式与分配方式 3.1分配方式 3.2模式 二、DHCP工作原理 1.四次回话 2.重新登录 3.更新租约 4.扩展 三、安装DHCP服务 四、DHCP局部配置并且测试 五、使用…

简介空间复杂度

我们承接上一篇博客。我们写了时间复杂度之后&#xff0c;我们就要来介绍一下另一个相关复杂度了。空间复杂度。我觉得大家应该对空间复杂度认识可能比较少一些。我就是这样&#xff0c;我很少看见题目中有明确要求过空间复杂度的。但确实有这个是我们不可忽视的&#xff0c;所…

在门店里造绿色氧吧!康养行业也这么卷了?

拼啥不如拼健康&#xff0c;现在的人算是活明白了&#xff0c;不但中老年人这样想&#xff0c;年轻人也这样干。你可能不知道&#xff0c;现在众多健康养生门店&#xff0c;逐渐成了年轻人“组团养生”的好去处&#xff0c;也是他们吃喝玩乐之外的新兴消费趋势。 而在看得见的…

无需服务器,浏览器跑700+AI模型?!【送源码】

Transformers.js 是一个创新的网络机器学习库&#xff0c;它将先进的 Transformer 模型直接带入浏览器&#xff0c;无需服务器端支持。这个库与 Hugging Face 的 Python transformers 库功能对等&#xff0c;提供相似的 API 接口来运行预训练模型&#xff0c;涵盖了自然语言处理…

Java引用的4种类型:强、软、弱、虚

在Java中&#xff0c;引用的概念不仅限于强引用&#xff0c;还包括软引用、弱引用和虚引用&#xff08;也称为幻影引用&#xff09;。这些引用类型主要用于不同的内存管理策略&#xff0c;尤其是在垃圾收集过程中。以下是对这四种引用类型的详细解释&#xff1a; 1. 强引用&am…

【实践分享】深度学习远程连接GPU

目录 前言 一、创建实例 二、上传文件 三、服务器上传 四、运行代码文件 前言 1、使用平台&#xff1a;恒源云 2、教程总结自B站大佬Larry同学发布的教程视频 一、创建实例 通俗&#xff1a;租用一台临时的电脑&#xff0c;电脑可自选GPU型号等&#xff0c;按照项目需…

品质至上!中国星坤连接器的发展之道!

在电子连接技术领域&#xff0c;中国星坤以其卓越的创新能力和对品质的不懈追求&#xff0c;赢得了业界的广泛认可。凭借在高精度连接器设计和制造上的领先地位&#xff0c;星坤不仅获得了多项实用新型专利&#xff0c;更通过一系列国际质量管理体系认证&#xff0c;彰显了其产…

【原理+使用】DeepCache: Accelerating Diffusion Models for Free

论文&#xff1a;arxiv.org/pdf/2312.00858 代码&#xff1a;horseee/DeepCache: [CVPR 2024] DeepCache: Accelerating Diffusion Models for Free (github.com) 介绍 DeepCache是一种新颖的无训练且几乎无损的范式&#xff0c;从模型架构的角度加速了扩散模型。DeepCache利…