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 命令,这样尽管不能避免麻烦,但能有所缓解。

 

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于最大相邻夹角的边缘点提取(matlab)

1、背景介绍 边缘点是指点云数据中代表物体或场景几何形状突变的那些点。在三维点云中&#xff0c;边缘点通常标志着不同表面或物体的分界&#xff0c;或者是物体表面上的不规则性&#xff0c;如裂缝、棱角、突起等。点云边缘检测的作用非常重要&#xff0c;最常见是进行特征点…

mac 安装nvm的教程

在macOS上切换Node.js版本&#xff0c;可以使用nvm&#xff08;Node Version Manager&#xff09;。以下是安装nvm和切换Node.js版本的步骤&#xff1a; 安装nvm 下载方式 终端复制输入&#xff1a; curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.…

基于Java+SpringMvc+Vue技术智慧校园系统设计与实现--60页及以上论文参考

博主介绍&#xff1a;硕士研究生&#xff0c;专注于信息化技术领域开发与管理&#xff0c;会使用java、标准c/c等开发语言&#xff0c;以及毕业项目实战✌ 从事基于java BS架构、CS架构、c/c 编程工作近16年&#xff0c;拥有近12年的管理工作经验&#xff0c;拥有较丰富的技术架…

7.Android逆向协议-抓取安卓http和https数据包(设备需要root权限)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a;微尘网校 上一个内容&#xff1a;6.Android逆向协议-配置FD抓包环境 工具下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s…

html+css+js贪吃蛇游戏

贪吃蛇游戏&#x1f579;四个按钮控制方向&#x1f3ae; 源代码在图片后面 点赞❤️关注&#x1f64f;收藏⭐️ 互粉必回&#x1f64f;&#x1f64f;&#x1f60d;&#x1f60d;&#x1f60d; 源代码&#x1f4df; <!DOCTYPE html> <html lang"en"&…

Maven Nexus3 私服搭建、配置、项目发布指南

maven nexus私服搭建 访问nexus3官方镜像库,选择需要的版本下载:Docker Nexus docker pull sonatype/nexus3:3.49.0 创建数据目录并赋权 sudo mkdir /nexus-data && sudo chown -R 200 /nexus-data 运行(数据目录选择硬盘大的卷进行挂载) docker run -d -p 808…

WPS+Python爬取百度之星排名

运行效果 手动拉取 https://www.matiji.net/exam/contest/contestdetail/146 如果手动查找&#xff0c;那么只能通过翻页的方式&#xff0c;每页10行&#xff08;外加一行自己&#xff09;。 爬取效果预览 本脚本爬取了个人排名和高校排名&#xff0c;可以借助WPS或MS Offi…

66.Python-web框架-Django-免费模板django-datta-able的分页的一种方式

目录 1.方案介绍 1.1实现效果 1.2django.core.paginator Paginator 类: Page 类: EmptyPage 和 PageNotAnInteger 异常: 1.3 templatetags 2.方案步骤 2.1创建一个common app 2.2创建plugins/_pagination.html 2.3 其他app的views.py查询方法 2.4在AIRecords.html里…

Table 表格--分页序号自增

代码&#xff1a; import { Space, Table, Tag } from antd; import type { ColumnsType } from antd/es/table; import React, { useState } from react;interface DataType {key: string;name: string;age: number;address: string;tags: string[]; }const data: DataType[]…

HTML5实现我的音乐网站源码

文章目录 作者&#xff1a;[xcLeigh](https://blog.csdn.net/weixin_43151418) 1.设计来源1.1 界面效果1.2 轮播图界面1.3 音乐播放界面1.4 视频播放界面 2.效果和源码2.1 动态效果2.2 源代码 源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff0c;在线沟通 作…

ImportError: DLL load failed while importing _imaging: 操作系统无法运行 %1

解决方案&#xff1a; &#xff08;1&#xff09;搜索打开Anaconda Prompt控制台&#xff0c;进入到自己要安装的环境下面去&#xff0c;卸载Pillow:pip uninstall Pillow 没有安装Pillow的就不用卸载&#xff0c;直接安装&#xff0c; &#xff08;2&#xff09;然后再安装&a…

常用的MRI分析软件

MRI&#xff08;磁共振成像&#xff09;分析软件种类繁多&#xff0c;涵盖了从基础图像处理到高级数据分析的各个方面。这些软件广泛应用于临床诊断、研究和教育等领域。以下是一些常用的MRI分析软件&#xff1a; 开源软件 商用软件 特殊用途软件 在线工具和云平台 这些软件各…

『C++成长记』string模拟实现

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;C &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ ​ 目录 一、存储结构 二、默认成员函数 &#x1f4d2;2.1构造函数 &#x1f4d2;2.…

Linux内核链表使用方法

简介&#xff1a; 链表是linux内核中最简单&#xff0c;同时也是应用最广泛的数据结构。内核中定义的是双向链表。 linux的链表不是将用户数据保存在链表节点中&#xff0c;而是将链表节点保存在用户数据中。linux的链表节点只有2个指针(pre和next)&#xff0c;这样的话&#x…

【Linux】记录一起网站劫持事件

故事很短&#xff0c;处理也简单。权当记录一下&#xff0c;各位安全大大们手下留情。 最近一位客户遇到官网被劫持的情况&#xff0c;想我们帮忙解决一下&#xff08;本来不关我们的事&#xff0c;毕竟情面在这…还是无偿地协助一下&#xff09;&#xff0c;经过三四轮“谦让…

多线程(进阶)

前言&#x1f440;~ 上一章我们介绍了线程池的一些基本概念&#xff0c;今天接着分享多线程的相关知识&#xff0c;这些属于是面试比较常见的&#xff0c;大部分都是文本内容 常见的锁策略 乐观锁 悲观锁 轻量锁 重量级锁 自旋锁 挂起等待锁 可重入锁和不可重入锁 互斥…

Python结合MobileNetV2:图像识别分类系统实战

一、目录 算法模型介绍模型使用训练模型评估项目扩展 二、算法模型介绍 图像识别是计算机视觉领域的重要研究方向&#xff0c;它在人脸识别、物体检测、图像分类等领域有着广泛的应用。随着移动设备的普及和计算资源的限制&#xff0c;设计高效的图像识别算法变得尤为重要。…

MPI hello world SSH 免密互联

目标&#xff1a; 我们想实现2台主机免密互联&#xff0c;将MPI Hello World跑起来 假设hostname是node01,node02,&#xff08;Linux shell窗口一般是UserNameHostName&#xff0c;node1和node2一定要和HostName一样&#xff09; hostname是/etc/hosts中的配置&#xff0c;如下…

并发编程-05AQS原理

并发编程-深入理解AQS之ReentrantLock 一 认识AQS 在讲解AQS原理以及相关同步器之前&#xff0c;我们需要对AQS有一些基本的认识&#xff0c;了解下它有什么样的机制&#xff0c;这样追踪源码的时候就不会太过于迷茫&#xff01; 1.1 什么是AQS java.util.concurrent包中的大…

JavaWeb—js(2)

函数 /* 创建一个方法形参不需要写参数类型&#xff0c;多个参数直接用逗号隔开就可以 */function show(a,b,c){console.log(我是show方法,a,b,c)return ab;}// 调用方法//调用方法时 形参个数如果和实参个数对不上不会有异常show();show(你好)show(1,2);let add show(1,2,3…