文章学习自:麦兜搞IT,如有侵权,告知删除

前言

合并操作在Git中属于最为核心的一个操作,包括三种合并方式:一种为fast forward ,需要满足有非常强的前提条件才能执行;一种为3 way merge方式,这种是我们工作中常见的;最后一种为变基rebase。另外,本篇文章也会深入讲解冲突如何产生,以及如何解决

1 Fast Forword 合并

1.1 核心原理

需求:将bugfix分支合并到master(切换到master然后执行git merge bugfix)

Fast Forword 合并: 将master分支指针向前快速移动到bugfix分支所指向的commit对象,在此合并方式下,不会产生冲突

前提条件: bugfix和master分支具有完全相同的提交历史(即bugfix提交历史中有master最新的提交)

1.2 举个栗子

合并前描述
master分支指向C2代表的commit对象,而bugfix超前于master分支1次提交(这里可以超前多次),指向了C3所代表的commit对象。符合fast forward merge
在这里插入图片描述

执行命令
git checkout master
git merge bugfix

合并后描述
master指针快速移动到bugfix指针所指向的commit对象C3
在这里插入图片描述

合并过程中发生的事情

1、.git/ 目录下会新增一个文件 ORIG_HEAD文件,该文件为指向master上一次commit的指针,用于回滚,即若发现合并错了,那执行git reset ORIG_HEAD即可完成回滚操作
2、不会产生新的commit、bolb、tree对象

fast-forward为什么不会产生冲突
冲突产生的原因:多个分支同一个文件同一部分进行了修改,并且这些修改是相互矛盾的,无法自动合并。而fast-forward只有一个分支对文件做了修改(bugfix)

1.3 经验之谈

在实际工作场景中,此合并方式基本不会遇到,除非代码仓库只有自己在维护。而我们通常遇到的情况都是下面要讲的3 way merge 或者rebase的情况,也即bugfix和master分支不具有完全相同的提交历史,产生了分叉

2 three way merge

2.1 核心原理

需求:将bugfix分支合并到master(切换到master然后执行git merge bugfix)

three way merge: Git 需要比较三个版本的代码,即两个分支的最新提交对象和它们的共同祖先提交对象。Git 使用一种叫做三方合并(three-way merge)的技术来自动合并这三个版本的代码。

合并过程:
1、找到两个分支的共同祖先提交对象,确定两个分支之间的修改范围,确定冲突的位置

2、比较两个分支的最新提交对象和共同祖先分支之间的差异,确定每个分支中的修改内容。

3、合并两个分支的修改。根据比较结果,Git 将两个分支的修改合并起来。如果两个分支对同一个文件的不同部分进行了修改,Git 将尝试自动合并这些修改。如果这些修改发生在同一个文件的同一个区域,Git 就会提示用户手动解决冲突。

2.2 举个栗子(不带冲突)

合并前描述
A用户对master执行了合并,使得master指针从C2变为了C4;B用户对bugfix执行了commit操作,使得bugfix从C2变为了C3,此时,产生了分叉。我们的目标是要将bugfix合并到master上
在这里插入图片描述

执行命令
git checkout master
git merge bugfix

此时会跳转到一个vim界面,编辑本次merge包括了哪些信息,这个自己填写就可以
在这里插入图片描述

合并后描述
产生一个新的commit对象C5,它的parent有两个,C3与C4,同时master指针指向C5,合并完成
在这里插入图片描述

2.3 带冲突的three way merge

合并前描述
master和bugfix对同一文件的同一区域进行了修改,现在要将bugfix分支合并到master
在这里插入图片描述
执行命令
git checkout master
git merge bugfix

此时会显示如下冲突信息
在这里插入图片描述

此时也可以使用git status来查看有哪些文件产生了冲突
在这里插入图片描述
然后可以使用git diff 冲突文件路径来查看差异,最后可以手动解决(git add git commit即可)。
当然目前有很多IDE内置了很方便的冲突解决功能

合并后描述
产生C4,parent是C2,C3,C4中的test.txt是你解决完冲突后的内容

3 变基rebase

git rebase命令适合有强迫症的人使用。

3.1 引入rebase

3 way merge方式在git历史线上会产生分叉,类似下面,红色代表dev,蓝色代表master
在这里插入图片描述
有些人就觉得,不行,必须得是直线才好看,也就是想在3 way merge的方式下还想达到fast forward的效果(fast forward在git 历史上是直线),所以产生了git rebase

3.2 核心原理

核心原理:将一个分支的修改“移动”到另一个分支上,使得两个分支的修改可以按照时间顺序排列,从而形成一个线性的提交历史

基本步骤
在这里插入图片描述
在 rebase完之后,可以checkou 到master执行merge操作,完成合并。
注意:rebase的过程中也是有可能产生冲突的,解决完冲突之后 使用git rebase --continue继续rebase

4 冲突问题

4.1 产生冲突的原因

核心原因多个分支同一个文件同一部分进行了修改,并且这些修改是相互矛盾的,无法自动合并。

具体来说,当多个分支对同一个文件的同一部分进行了修改时,Git 会尝试自动合并这些修改,并将合并结果应用于最终合并结果中。但是,如果这些修改是相互矛盾的,例如一个分支将文件的某个部分删除了,而另一个分支对该部分进行了修改,则 Git 就无法自动合并这些修改,会提示合并冲突。

在这种情况下,开发者需要手动解决冲突,从而完成合并操作。手动解决冲突的过程中,开发者需要根据需要保留、修改或删除对应的代码行或代码段。解决冲突后,开发者需要将修改提交到 Git 仓库中。

4.2 常见冲突场景

1、git merge时(3 way merge)
2、git pull时

以下场景不会产生冲突:

场景一:
假设有两个分支,分别是 A 和 B,它们都对同一个文件 file.txt 进行了修改:

分支 A 对 file.txt 进行了删除操作; 分支 B 对 file.txt 进行了修改操作。 这时候,如果要合并这两个分支,Git就会自动先将分支 B 对 file.txt 的修改操作合并到最终合并结果中,再将A 对 file.txt 的删除操作合并到最终合并结果中,而不会提示合并冲突
最终合并的结果是file文件被删除了

4.3 解决冲突

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐