Close

git merge

合并是 Git 将拷贝历史记录重新组合在一起的方式。git merge 命令允许您采用 git branch 创建的独立开发行,并将它们集成到单个分支中。

请注意,下面显示的所有命令都合并到当前分支中。当前分支将更新以反映合并,但目标分支将完全不受影响。同样,这意味着 git merge 通常与 git checkout 结合使用来选择当前分支,使用 git branch-d 来删除过时的目标分支。


工作原理


Git merge 会将多个提交序列合并为一个统一的历史记录。在最常见的用例中,git merge 用于合并两个分支。本文档中的以下示例将重点介绍这种分支合并模式。在这些场景中,git merge 需要两个提交指针,通常是分支提示,并会在它们之间找到一个共同的基础提交。一旦 Git 找到通用基础提交,它将创建一个新的“合并提交”,该提交组合了每个排序合并提交的变更。

假设我们有一个基于 main 分支的新分支功能。我们现在想将这个功能分支合并到 main 分支中。

将 feature 分支合并到 main 分支
控制台窗口
相关资料

高级 Git 日志

Bitbucket 徽标
查看解决方案

了解 Bitbucket Cloud 的 Git

调用此命令会将指定的分支功能合并到当前分支中,我们假设为 main。Git 将自动确定合并算法(如下所述)。

新的合并提交节点

与其他提交相比,合并提交的独特之处在于,它们有两个父项提交。创建合并提交时,Git 会尝试自动为您合并单独的历史记录。如果 Git 遇到在两个历史记录中都发生了变更的数据,它将无法自动合并这些数据。这种情况是版本控制冲突,Git 需要用户干预才能继续。

正在准备合并


执行合并之前,需要采取几个准备步骤来确保合并顺利进行。

确认接收分支


执行 git status 以确保 HEAD 指向正确的合并接收分支。如果需要,执行 git checkout ,切换到接收分支。在我们的例子中,我们将执行 git checkout main

获取最新的远程提交


确保接收分支和合并分支是最新的远程变更。执行 git fetch 以提取最新的远程提交。提取完成后,通过执行 git pull 确保 main 分支有最新的更新。

合并


完成前面讨论的“准备合并”步骤后,可以通过执行 git merge 来启动合并,其中 是将要合并到接收分支的分支名称。

快进合并


当存在从当前分支尖端到目标分支的线性路径时,可能会发生快进合并。不是“实际上”合并分支,Git 要整合历史记录,所要做的就是将当前分支的尖端向上移动(即“快进”)到目标分支的尖端。这有效地合并了历史记录,因为所有可从目标分支访问的提交现在都可以通过当前分支获得。例如,将 some-feature 快进合并到 main 会如下所示:

位于主节点之前的功能节点,快进后,两个节点都在同一个节点上

但是,如果分支出现分歧,则不可能进行快进合并。当目标分支没有线性路径时,Git 别无选择,只能通过三向合并将它们合并。三向合并使用专用提交将两个历史记录联系在一起。这个命名法源于 Git 使用三个提交来生成合并提交:两个分支提示及其共同的祖先。

三向合并后的示意图

虽然您可以使用这两种合并策略中的任何一种,但许多开发人员喜欢使用快进合并(通过变基来促进)来修复小功能或缺陷,并保留三向合并用于集成长期运行的功能。在后一种情况下,生成的合并提交充当两个分支的符号连接。

我们的第一个示例演示了快进合并。下方代码创建了一个新分支,向其添加了两个提交,然后通过快进合并将其集成到主行中。

# Start a new feature
git checkout -b new-feature main
# Edit some files
git add <file>
git commit -m "Start a feature"
# Edit some files
git add <file>
git commit -m "Finish a feature"
# Merge in the new-feature branch
git checkout main
git merge new-feature
git branch -d new-feature

这是短期主题分支的常见工作流程,这些分支更多地被用作孤立的开发,而不是用于长期运行的功能的组织工具。

另请注意,Git 不应该抱怨 git branch -d,因为现在可以从 main 分支访问 new-feature。

如果您在快进合并期间需要合并提交以保存记录,则可以使用 --no-ff 选项执行 git merge

git merge --no-ff <branch>

此命令将指定的分支合并到当前分支中,但始终生成合并提交(即使是快进合并)。这对于记录存储库中发生的所有合并很有用。

三向合并


下个示例非常相似,但需要进行三向合并,因为 main 分支在功能进行时会继续进行。这是大型功能或多个开发人员同时开发一个项目的常见场景。

Start a new feature
git checkout -b new-feature main
# Edit some files
git add <file>
git commit -m "Start a feature"
# Edit some files
git add <file>
git commit -m "Finish a feature"
# Develop the main branch
git checkout main
# Edit some files
git add <file>
git commit -m "Make some super-stable changes to main"
# Merge in the new-feature branch
git merge new-feature
git branch -d new-feature

请注意,Git 不可能执行快进合并,因为如果不回溯,就无法将 main 升级到 new-feature

对于大多数工作流程来说,new-feature 将是一个更大的功能,需要很长时间才能开发,这就是新提交会同时出现在 main 上的原因。如果您的功能分支实际上和上面例子中的分支一样小,那么您最好将其变基到 main 上,然后进行快进合并。这样可以防止多余的合并提交扰乱项目历史记录。

解决冲突


如果您要合并的两个分支都变更了同一个文件的相同部分,Git 将无法确定要使用哪个版本。发生这种情况时,它会在合并提交之前停止,以便您可以手动解决冲突。

Git 合并流程的很大一部分是它使用熟悉的编辑/暂存/提交工作流程来解决合并冲突。遇到合并冲突时,运行 git status 命令会显示需要解决哪些文件。例如,如果两个分支都修改了 hello.py 的同一部分,您会看到类似下方的内容:

On branch main
Unmerged paths:
(use "git add/rm ..." as appropriate to mark resolution)
both modified: hello.py

冲突是如何呈现的


在合并期间遇到冲突时,Git 将会使用可视指示器来编辑受影响文件的内容,并在冲突内容的两边标上标记。用到的视觉标记包括:<<<<<<<、======= 和 >>>>>>>。在合并期间,在项目中搜索这标记可以轻松找到需要解决冲突的地方,非常实用。

here is some content not affected by the conflict
<<<<<<< main
this is conflicted text from main
=======
this is conflicted text from feature branch
>>>>>>> feature branch;

通常 ======= 标记之前的内容是接收分支,之后的部分是合并分支。

一旦您确定了有冲突的部分,您就可以进入并根据自己的喜好修复合并。当您准备好完成合并时,您要做的就是在冲突文件上运行 git add,告诉 Git 它们已经解决了。然后,运行一个普通的 git commit 来生成合并提交。这与提交普通快照的流程完全相同,这意味着普通开发人员可以轻松管理自己的合并。

请注意,只有在三向合并的情况下才会发生合并冲突。在快进合并中不可能有相互冲突的变更。

摘要


本文档概述了 git merge 命令。使用 Git 时,合并是一个必不可少的过程。我们讨论了合并背后的内部机制,以及快进合并和三向真正合并之间的区别。一些关键的要点如下所示:

1. Git 合并将提交序列合并为一个统一的提交历史记录。

2. Git 的合并方式主要有两种:快进和三向

3. Git 可以自动合并提交,除非两个提交序列中存在冲突的变更。

本文档集成并引用了其他 Git 命令,例如:git branchgit pullgit fetch。访问他们相应的独立页面以获取更多信息。


分享此文章
下一主题

推荐阅读

将这些资源加入书签,以了解 DevOps 团队的类型,或获取 Atlassian 关于 DevOps 的持续更新。

人们通过满是工具的墙进行协作

Bitbucket 博客

Devops 示意图

DevOps 学习路径

与 Atlassian 专家一起进行 Den 功能演示

Bitbucket Cloud 与 Atlassian Open DevOps 如何协同工作

注册以获取我们的 DevOps 新闻资讯

Thank you for signing up