Git
git merge

git merge命令:解决冲突,重新放置压扁差异,合并策略

在这篇文章中,我们将介绍git merge方法。从如何合并到解决冲突,合并提交的特点,合并策略,与rebase和squash的区别,以及git merge命令的其他选项。

1. 如何合并一个分支

git merge命令是用来将一个分支合并到另一个分支。

git branch post中,我提到分支名称是该分支的最后一次提交。 同样的道理,合并分支最终会创建一个新的提交,其中包含两个分支最后一次提交的所有修改、 你也可以把它看成是对运行git merge命令的工作分支的一次新提交。

git merge命令总是在创建该分支的地方执行合并提交。 例如,如果你要从 main分支合并 feature-a分支,你会使用这样的命令

$ git switch main
switched to branch 'main'
 
$ git merge feature-a
Merge made by the 'ort' strategy

在上面的例子中,你可以看到我们使用了merge-ort策略,这是Git最新的默认合并策略,于2022年改变。

1.1. ort策略

在进入下一节之前,让我们先来看看Git最新的合并算法,ort策略。

ort是 "Ostensibly Recursive's Twin "的缩写,意味着它是为了取代旧的默认算法,recursive策略而创建的。 与 recursive策略相比,据说它可以减少冲突并照顾到重命名的文件。

它基本上是基于三向合并算法,比较三个来源的变化:两个分支的同一祖先提交、两个分支的最新提交和两个分支的最新提交,然后执行一个 合并。在合并两个分支时,我们主要使用ort策略,因为它比之前使用的resolverecursive策略表现更好。

其他值得了解的策略是用于合并两个或多个分支的octopus策略,或者用于合并到子目录的subtree策略。 现在,让我们先熟悉一下这些名称。

这些策略可以用-s--strategy选项来指定,如下所示。

$ git merge -s recursive feature-a

2. How to resolve a merge conflict## 2. 如何解决合并冲突

当两个不同分支上的同一文件中的同一行内容不同时,就会发生合并冲突。 为了保存数据,除非你在策略中给它一个选项,否则Git绝不会任意删除某些东西。相反,它将暂停合并,给我们一个选择。

让我们看看这个动作。

首先,我们修改了1.md文件,在maindevelop两个分支中的内容不同。 然后,当我们进入main分支并试图合并develop分支时,我们得到一个合并冲突。

创建合并冲突

如果你对git commit命令的-a选项感到陌生,请参阅git commit post

此时,Git 会在有冲突的文件内容中添加诸如 <<<<<<< HEAD, =======, >>>>>>> branch-name 的符号,让你知道到底有什么需要修正的。 让我们打开1.md文件。

合并冲突情况

这是在Neovim编辑器中打开的1.md文件。我们只需要在这部分保留我们想要的东西,删除Git添加的符号,然后继续提交。

在一个支持Git的编辑器中,合并就更容易了,比如VSCode。高亮显示很直观,按下上面四句话的按钮<<<<<<< HEAD就会自动删除排除的内容和Git的符号。

vscode合并冲突情况

修改完内容后,像正常提交一样用git commit命令完成合并。

git merge 冲突解决

3. 与rebase的区别

git mergegit rebase命令有一些共同点:它们都是合并两个分支和解决合并冲突的方法。 然而,它们的工作方式还是有区别的,了解它们很重要,这样你就可以根据自己的需要选择正确的命令。

git merge命令创建一个新的合并提交,将两个分支的最后一个提交作为其父分支,如上图所示。 结果,提交历史中出现了两个分支一起对应的提交。 feature-afeature-b等路径在主路径上来来回回,称为 main分支。

git rebase命令将两个分支合并,这样提交历史中就没有死角了。 这比你想象的要简单。让我们看一下下面的图片。

git rebase解释

假设你想把feature-a分支合并到main分支,该分支从一个共同的祖先提交A中分化出来,git rebase命令会创建一个新的提交,其改动与feature-a中的提交相同。 在图中,这些是CD的提交。

这两个提交被附加到B,即main分支的最后一个提交。 这样就形成了一个提交历史,但结果是,feature-a分支的所有修改都可以合并到main分支。 历史记录也更简单,因为我们不需要创建一个新的合并提交。

然而,我们不容易一眼看出CD两个提交是来自不同分支的合并提交,还是之前在main分支的提交。 所以从历史的角度来看,你正在失去信息。

出于这个原因,你应该在适当的情况下使用merge和rebase,这取决于你的团队所采取的方向。 关于git rebase命令的更多信息,见本帖

4. 与Squash的区别

Squash是Git中的一个概念,将多个提交压缩成一个。 它并不作为一个单独的命令存在,但可以作为合并或重构命令的一个选项使用。 当git merge命令使用--squash选项时,它被称为squash合并。

让我们看看下面的图片来理解squash merge。

理解squash merge

在当前提交的 8c12中,maindevelop两个分支被分割。 我试着在main分支上进行squash合并,结果顺利通过。

下面的 git status命令的结果显示,develop分支的所有提交都在 main分支上进行了缓存。

git squash 合并执行结果

如果你检查提交后的历史,你会发现develop分支仍未被合并,但它的改动已经被登记为main的新提交。 这就是挤压式合并的作用。

在重建过程中也可以使用squash选项,不同的是,develop分支的历史不会像上面那样留下。 我们将在rebase帖子中再次介绍这个问题。

5. 最后的想法

我认为合并冲突是Git初学者最先卡住的事情之一。 然而,合并和解决合并冲突是Git协作的核心,所以理解和掌握它们很重要。 我希望这篇文章能帮助你入门。

copyright for git merge

© 2023 All rights reserved.