Git merge

Git merge

参考文档:

https://marsishandsome.github.io/2019/07/Three_Way_Merge

https://git-scm.com/docs/merge-strategies

https://stackoverflow.com/questions/56889406/how-does-git-compare-two-files-while-merging

Git merge的目标是合并changes,但是Git并不存储changes。Git存储的是snapshots。从每个commit可以都可以获取到整个文件的,git可以从这个commit中获取整个文件。进行比较及合并。

一、Three-way merge

Git如何帮助我们进行merge操作的

Two-way merge

Two-way merge解决的问题是:如何把两个文件进行合并。

举例:假设你和另外一个人同时修改了一个文件,这时merge算法看到了这两个文件,如下图:
在这里插入图片描述
merging算法发现两个文件大部分都是一样,只有30行不一样,

  • Yours的版本里内容是:Print("hello")
  • Mine的版本里内容是:Print("bye")

但是merging算法怎么知道是你修改了30行还是另外一个人修改了?可能会有以下几种情况:

  1. Mine版本没有修改,Yours版本修改了内容(从Print("bye") 修改 Print("hello"))
  2. Yours版本没有修改,Mine版本修改了内容(从Print("hello") 修改 Print("bye")
  3. YoursMine都修改了内容,(Yours???修改成Print("hello")Mine???修改成Print("bye")
  4. YoursMine都增加了一行

对于一个merge算法来说,该怎么处理上述4中情况呢?

  1. Mine版本没有修改,Yours版本修改了内容 => 应该选Yours版本
  2. Yours版本没有修改,Mine版本修改了内容 => 应该选Mine版本
  3. YoursMine都修改了内容 => 需要手动解决冲突
  4. YoursMine都增加了一行 => 需要手动解决冲突

由于缺乏必要的信息,Two-way merge根本无法帮助我们解决冲突,TA只能帮助我们发现冲突,需要手动解决冲突。

如果让merging算法知道更多一些信息,merging算法是否可以帮助我们自动解决一些简单的冲突呢?下面来看一下Three-way merge算法。

Three-way merge

Three-way merge是在Two-way merge的基础上又增加了一个信息,即两个需要合并的文件修改前的版本。如下图所示,merge算法现在知道三个信息:

  1. Mine:需要合并的一个文件
  2. Yours:另一个需要合并的文件
  3. Base:两个文件修改前的版本

在这里插入图片描述

这时merging算法发现:

  • 修改前的Base版本里的内容是:Print("bye")
  • Yours的版本里内容是:Print("hello")
  • Mine的版本里内容是:Print("bye")

说明Yours对这一行做了修改,而Mine对这行没有做修改,因此对YoursMine进行merge后的结果应该采用Yours的修改,于是就变成Print("hello")

这就是Three-way merge的大致原理。

Three-way merge 冲突案例

我们来看一个更加复杂的案例,如下图:

在这里插入图片描述

按行对比两个文件后,merging算法发现有3个地方不一样,分别是:

  1. 30行:上文描述的冲突案例
  2. 51行:有一个for循环被同时修改
  3. 70行:Mine的版本里面新增了一行

在这里插入图片描述

我们来看一下这三种冲突改怎么解决:

  1. 30行:只有Yours修改了,因此使用Yours的版本
  2. 51行:YoursMine都修改了,需要手工解决冲突
  3. 70行:Mine新增了一行,因此使用Mine的版本

使用Three-way merge进行merge

我们来看下git是如何使用Three-way merge来进行git merge操作的。

先来看下git merge在官网的定义:

git-merge - Join two or more development histories together

即把两个或两个以上的开发历史进行合并。

这样讲比较抽象,来看一个简单的例子,假设我们有2个branch:

  • main:master branch
  • task001:我们正在开发的branch

第一次Merge:main -> task001

我们在task001上开发了一段时间,需要把main上的修改合并到task001,这时可以运行

$ git checkout task001
$ git merge main

在这里插入图片描述

merge后结果如下

在这里插入图片描述

merge的过程其实就是使用Three-way merge,其中

  1. Base = commit 1
  2. Mine = commit 4
  3. Yours = commit 3

merge后会生成一个新的merge节点commit 5,并且commit 5会同时依赖commit 3commit 4

使用Three-way merge进行cherry-pick

cherry-pick 在官网的定义如下:

git-cherry-pick - Apply the changes introduced by some existing commits

即把已经有的commit apply到其他分支,git cherry-pick其实也是使用Three-way merge,其中:

  1. Mine = 执行cherry-pick时所在的branch的HEAD
  2. Yours = 被cherry-pick的那个commit
  3. Base = 被cherry-pick的那个commit的前一个commit

这样讲比较抽象,举个例子:

E <-- master
|
D
| C <-- foo_feature(*)
|/
B
|
A

假设我们目前在foo_feature分支,运行git cherry-pick D,这时Three-way merge的参数:

  • Mine = C
  • Yours = D
  • Base = B

假设我们目前在foo_feature分支,运行git cherry-pick E,这时Three-way merge的参数:

  • Mine = C
  • Yours = E
  • Base = D

使用Three-way merge进行rebase

rebase官方定义如下:

git-rebase - Reapply commits on top of another base tip

即使用其他分支作为基础,重新apply当前分支所有的commit,git rebase的过程可以看做是不断的做git cherry-pick,举个例子:

E <-- master
|
|   F <-- foo_feature(*)
D  /
| C
|/
B
|
A

foo_feature branch运行下面运行git rebase master命令,就会变成下面的样子:

E <-- master
|
|       F <-- foo_feature(*)
|      /
|     C
D    /
|   E
|  /
| D
|/
B
|
A

相当于运行了下面几个命令:

git checkout master
git checkout -b foo_feature_rebased
git cherry-pick C
git cherry-pick F

二、Merge commit

https://stackoverflow.com/questions/40986518/how-to-git-show-the-diffs-for-a-merge-commit

定义:

合并提交(merge commit)是当两个分支的共同祖先不是最新提交时,Git创建一个新的提交来合并这两个分支的更改。

在 Git 中,当你执行 git merge 命令将一个分支合并到另一个分支时,Git 会创建一个特殊的提交,称为 “merge commit”。这个提交记录了两个分支合并的点,它有两个父提交:一个是你当前所在的分支的最新提交,另一个是你合并进来的分支的最新提交。

选择策略:

当你希望在 Git 历史中保留明确的合并点时,或者需要合并来自不同分支的更改,而这些更改不能简单地通过移动 HEAD 指针来完成时,使用合并提交是合适的。

Merge commit的内容:

通常包括

  1. 标题(Title)
    • 通常以 “Merge” 开头,后面跟着被合并分支的名称。
    • 例如:“Merge branch ‘feature-branch’ into ‘main’”
  2. 作者(Author)
    • 合并提交的作者通常是执行 git merge 命令的用户。
  3. 提交者(Committer)
    • 通常与作者相同,但有时可能会不同,尤其是在使用 git merge --no-ff 选项时。
  4. 日期(Date)
    • 合并提交的日期和时间。
  5. 消息(Message)
    • 通常包含更多关于合并的详细信息,可能包括被合并分支的提交范围和合并的原因。
  6. 父提交(Parent Commits)
    • 合并提交有两个父提交,分别指向两个分支的最新提交。
  7. 变更内容(Changes)
    • 合并提交可能包含文件的变更,这些变更是两个分支差异的结果。

注意:

  • 合并提交是 Git 历史的一部分,并且会永久存储在仓库中。
  • 使用 git merge --no-ff 选项可以确保即使在快进合并的情况下也会创建一个合并提交。
  • 合并提交可以帮助理解项目的历史和分支的合并点,但有时也可能使 Git 历史变得复杂。

查看 Merge Commit

git log --oneline --decorate --graph --all

这个命令会显示一个简化的 Git 历史图,包括所有的分支和合并提交。合并提交通常会有以下格式:

e43b5c2 (HEAD -> main, tag: v1.0, origin/main) Merge branch 'feature-branch'

在这个例子中:

  • e43b5c2 是合并提交的 SHA-1 哈希值。
  • HEAD -> main 表示当前 HEAD 指向 main 分支。
  • tag: v1.0, origin/main 表示合并提交也被标记为版本 v1.0,并且与远程 originmain 分支同步。

查看合并提交的详细内容:

git show e43b5c2

查看合并提交的diff:

git show -m c05f017
git show --first-parent c05f017
git diff c05f017^ c05f017

由于普通commit只有一个parent,所以git show可以明确的找到比较的对象。但是由于merge commit有两个parents,这时就需要指定parent。

c05f017和c05f0171都是代表第一个parent,c05f017^2代表第二个parent。

回退Merge commit

在这里插入图片描述

非merge commit 通过git revert xxx 命令即可产生一个回退commit。

但是merge类commit使用git revert xxx 命令,此时会报错commit is a merge but no -m option was given.,这是因为当前的merge commit其实包含了两个子commit,也就是当时合并的两个commit,因此在执行git revert 的时候会失败,需要选择回滚具体的哪一路的提交。

  1. 分析log, 确认要回退的commit

我们通过git log xxx 可以看到当前commit下的Merge: f2fe8c9 6103926,第二个id:6103926就是我要回滚的commitid。

具体要回退哪一路commit,可以通过git log --oneline --decorate --graph --all 图形化查看。

  1. 运行回退命令
git revert -m 1 xxx

注意:xxx为merge commit的commitid。

因此在执行git revert 的时候会失败,需要选择回滚具体的哪一路的提交。

  1. 分析log, 确认要回退的commit

我们通过git log xxx 可以看到当前commit下的Merge: f2fe8c9 6103926,第二个id:6103926就是我要回滚的commitid。

具体要回退哪一路commit,可以通过git log --oneline --decorate --graph --all 图形化查看。

  1. 运行回退命令
git revert -m 1 xxx

注意:xxx为merge commit的commitid。

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

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

相关文章

idea一键为实体类赋值

file -> settings -> plugins -> marketplace 把这个插件装上 找个实体&#xff0c;选中&#xff0c;altenter进入edit界面 我是选择只保留右边这种生成方法&#xff0c;然后选择ok 返回到那个实体&#xff0c;选择&#xff0c;altenter generate生成

创建线程的几种方式

严格来讲&#xff0c;创建线程只有一种方式&#xff0c;就是实现Runnable接口&#xff0c;其他创建线程的方式也是对其封装。 继承Thread方式 public class Thread extends java.lang.Thread {Overridepublic void run() {super.run();} } 进入Thread可以看到&#xff0c;也是…

Spark实时(四):Strctured Streaming简单应用

文章目录 Strctured Streaming简单应用 一、Output Modes输出模式 二、Streaming Table API 三、​​​​​​​​​​​​​​Triggers 1、​​​​​​​unspecified&#xff08;默认模式&#xff09; 2、​​​​​​​​​​​​​​Fixed interval micro-batches&am…

C语言刷题小记2

前言 本篇博客还是为大家分享一些C语言的OJ题目&#xff0c;如果你感兴趣&#xff0c;希望大佬一键三连。多多支持。下面进入正文部分。 题目1竞选社长 分析&#xff1a;本题要求我们输入一串字符&#xff0c;并且统计个数的多少&#xff0c;那么我们可以通过getchar函数来获…

软件开发者消除edge浏览器下载时“此应用不安全”的拦截方法

当Microsoft Edge浏览器显示“此应用不安全”或者“已阻止此不安全的下载”这类警告时&#xff0c;通常是因为Windows Defender SmartScreen或者其他安全功能认为下载的文件可能存在安全风险。对于软件开发者来说&#xff0c;大概率是由于软件没有进行数字签名&#xff0c;导致…

【React】useState:状态更新规则详解

文章目录 一、基本用法二、直接修改状态 vs 使用 setState 更新状态三、对象状态的更新四、深层次对象的更新五、函数式更新六、优化性能的建议 在 React 中&#xff0c;useState 是一个非常重要的 Hook&#xff0c;用于在函数组件中添加状态管理功能。正确理解和使用 useState…

未来的智能交通系统:智能合约在交通管理中的应用前景

随着城市化进程的加快和交通问题日益突出&#xff0c;智能交通系统成为了解决城市交通拥堵和安全问题的重要手段。本文将探讨智能合约在未来智能交通系统中的应用前景&#xff0c;分析其在交通管理中的潜力和优势。 什么是智能交通系统&#xff1f; 智能交通系统利用先进的信息…

MySQL之索引及简单运用

索引&#xff1a; 什么是索引 索引是数据库中一种非常重要的数据结构&#xff0c;用于帮助快速查询数据库表中的数据。它就像一本书的目录&#xff0c;能够让你快速定位到书中的某个具体章节或内容&#xff0c;而不需要一页一页地翻阅整本书。 在数据库管理系统中&#xff0c;…

设计模式 之 —— 单例模式

目录 什么是单例模式&#xff1f; 定义 单例模式的主要特点 单例模式的几种设计模式 1.懒汉式&#xff1a;线程不安全 2.懒汉式&#xff1a;线程安全 3.饿汉式 4.双重校验锁 单例模式的优缺点 优点&#xff1a; 缺点&#xff1a; 适用场景&#xff1a; 什么是单例模…

VBA实例-从Excel整理数据到Word

实现目录 功能需求数据结构复制数据到新sheet并分类数据添加序号、日期、时间三列数据添加序号列添加时间列 将名称和类别复制到word文件中将参数5和参数9中的一个复制到word文件中 实例 功能需求 1、将原始数据中不要的数据剔除 2、原始数据中增加序号、日期和时间三列数据&a…

图片上传成功却无法显示:静态资源路径配置问题解析

1、故事的背景 最近&#xff0c;有个学弟做了一个简单的后台管理页面。于是他开始巴拉巴拉撘框架&#xff0c;写代码&#xff0c;一顿操作猛如虎&#xff0c;终于将一个简单的壳子搭建完毕。但是在实现功能&#xff1a;点击头像弹出上传图片进行头像替换的时候&#xff0c;卡壳…

三星Unpacked发布会即将举行:有新款折叠屏手机,还有智能戒指

随着7月的脚步渐近&#xff0c;科技界的目光再次聚焦于三星&#xff0c;它即将在法国巴黎举办今年的第二场Unpacked发布会。这不仅是一场新品的展示&#xff0c;更是三星对创新科技的一次深刻诠释。 从Galaxy Z Fold 6的全新设计&#xff0c;到Galaxy Z Flip 6的显著升级&…

CSS实现表格无限轮播

<div className{styles.tableTh}><div className{styles.thItem} style{{ width: 40% }}>报警名称</div><div className{styles.thItem} style{{ width: 35% }}>开始时间</div><div className{styles.thItem} style{{ width: 25% }}>状态&…

《后端程序猿 · @Value 注释说明》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

【Unity PC端打包exe封装一个并添加安装引导】

Unity PC端打包exe封装一个并添加安装引导 比特虫在线制作ico图标ico图标转换工具 选中打包出来的所有文件和ico图标 右键 使用RAR软件 添加到压缩文件 两个名称要相同 设置完点击确认等待压缩完成 然后就可以使用 Smart Install Maker制作引导安装程序了

解决Pycharm找不到conda可执行文件

解决&#xff1a; 在 ‘Conda 可执行文件’ 的输入框里面&#xff0c;找到并选中 anaconda\library\bin 路径下的“ conda.bat ” ,再点击‘ 加载环境 ’&#xff0c;即可出现 ‘ 使用现有环境 ’ 的输入框&#xff0c;如图所示。

【实现100个unity特效之8】使用ShaderGraph实现2d贴图中指定部分局部发光效果

最终效果 寒冰法师 火焰法师 文章目录 最终效果寒冰法师火焰法师 素材一、功能分析实现方法基本思路Unity的Bloom后处理为什么关键部位白色&#xff1f;最终结果 二、 新建URP项目三、合并图片四、使用PS制作黑白图片方法一 手动涂鸦方法二 魔棒工具1. 拖入图片进PS&#xff0…

Unity3d打包到Android

本文参考&#xff1a; Unity3D新手教程&#xff1a;如何打包发布到Android_哔哩哔哩_bilibili 一、Unity 打包Android的环境搭建 1、工具安装 Unity Hub已经集成了Android的环境搭建。 选择Add modules 然后安装Android Build Support下的所有工具。 如果各个工具都安装成功…

给Windows系统中注入服务,即windwos守护进程

最近总是在windwos环境下测试nginx&#xff0c;总是需要频繁重启nginx服务。于是考虑有没有可能把nginx加入到系统服务的操作。在网上找了一大堆资料&#xff0c;现在来总结一下&#xff01; 方法1&#xff1a;利用nssm工具实现 这是一个守护进程的软件&#xff0c;可以在win…

Optima: 一个用于 Tapestri 平台的单细胞多组学数据分析的开源 R 包

分子条形码技术的最新进展使得在单细胞水平进行下一代转录组测序成为可能&#xff0c;例如10 Genomics Chromium和DropSeq。此外&#xff0c;CITE-seq 的出现使得可以在对单个细胞进行转录组分析的基础上同时对表面蛋白进行分析。同时&#xff0c;为了表征 DNA 和蛋白质谱&…