1. 命令概述

git merge 命令的主要作用是将两个或多个开发历史(分支)合并在一起。它可以将指定分支的修改集成到当前分支(HEAD 所指向的分支)。

它的核心逻辑是:

1.找到当前分支与目标分支的最近共同祖先
2.将当前分支和目标分支自共同祖先之后的所有更改进行合并。
3.创建一个新的 “合并提交” 来记录这次合并(除非是快进合并)。

2. 命令格式

基本的命令格式非常简单:

git merge [选项] <commit或分支名>
  • <commit或分支名>:通常是一个分支名(如 feature/login),表示你想将那个分支的更改合并过来。它也可以是一个具体的提交 ID。
  • [选项]:常用的选项我们会在下面详细介绍。

3. 基本用法

假设我们有一个典型的仓库,其提交历史如下所示:

      A---B---C feature/login
     /
D---E---F---G main

你当前在 main 分支(即 HEAD -> main),现在想要将 feature/login 分支的工作成果合并进来。

3.1 执行合并

# 1. 首先,确保你当前在目标分支上(main)
git checkout main

# 2. 然后,执行合并命令,将 feature/login 合并到 main
git merge feature/login

3.2 合并的三种结果

执行上述命令后,根据分支历史的不同,会产生三种主要结果:

3.2.1 快进合并

如果目标分支(main)的尖端是待合并分支(feature/login)的直接祖先,Git 会简单地将指针向前移动。因为这种合并没有需要解决的分歧,所以被称为“快进”。

合并后的历史会变成一条直线:

      A---B---C feature/login, main
     /
D---E---F---G

(实际上,main 指针直接移动到了 C 提交的位置)

3.2.2 三方合并

如果自两个分支分叉以来,当前分支(main)也有新的提交,Git 无法进行快进。这时,它会进行一次三方合并,使用共同祖先(E)、当前分支的尖端(G)和待合并分支的尖端(C)来创建一个新的合并提交。
合并后的历史会有一个分叉和汇合:

      A---B---C feature/login
     /         \
D---E---F---G---H main

这个新的 H 提交有两个父提交(GC),它记录了这次合并行为。

3.2.3 合并冲突

如果在同一文件的同一行,两个分支都有修改,Git 无法自动决定使用哪个版本,就会产生合并冲突。
Git 会暂停合并过程,并标记出文件中的冲突区域,等待你手动解决。

<<<<<<< HEAD
这是当前分支(main)的内容
=======
这是 feature/login 分支的内容
>>>>>>> feature/login

解决冲突的步骤:
1.编辑文件:手动选择要保留的内容,或者进行重构,然后删除 Git 添加的冲突标记(<<<<<<<, =======, >>>>>>>)。
2.标记为已解决:使用 git add <文件名> 将解决后的文件暂存。这告诉 Git 冲突已经解决。
3.完成合并:所有冲突都解决并 add 后,执行 git commit 来最终完成合并提交。

4. 高级用法

4.1 --no-ff (禁用快进合并)

强制 Git 总是创建一个新的合并提交,即使可以进行快进合并。

git merge --no-ff feature/login

为什么要用它?

  • 保留历史信息:在历史记录中明确能看到一个合并事件和特性的引入,避免了快进合并导致特性分支的历史被淹没在主线中。
  • 便于回溯:如果出了问题,更容易找到是哪个合并引入的。
  • 这是很多团队推荐的工作流实践。

4.2 --squash (压缩合并)

将待合并分支上的所有提交的更改“压缩”成一次新的提交,然后应用到当前分支。它不会真正地合并历史,也不会创建合并提交

git merge --squash feature/login

执行此命令后,更改会被应用到工作区和暂存区,但不会自动提交。你需要手动执行一次提交。

git commit -m "Squashed all commits from feature/login"

为什么要用它?

  • 保持主线整洁:对于一个开发过程中有很多琐碎提交的特性分支,在合并到主分支时,可以将其压缩成一个清晰的、有意义的提交。
  • 注意:使用 --squash 后,原始分支的历史会丢失,它不再是真正的“合并”。

4.3 -m (添加提交信息)

如果合并是自动创建的(非快进且无冲突),Git 会为你生成一个默认的提交信息,如 “Merge branch ‘feature/login’”。你可以使用 -m 选项来自定义这个信息。

git merge -m "Integrate user authentication feature" feature/login

4.4 --abort (中止合并)

如果在合并过程中遇到冲突,而你决定放弃这次合并,想回到合并前的状态,可以使用这个命令。

git merge --abort	

你的仓库会恢复到 git merge 命令执行之前的状态。

5. 注意事项

5.1 确保工作区清洁

在执行 git merge 前,最好使用 git status 检查工作区是否干净。如果有未提交的更改,可能会与合并内容冲突,导致合并失败

5.2 先拉取再合并

如果你的当前分支有远程跟踪分支(如 main 跟踪 origin/main),在合并其他分支前,最好先执行 git pull 来同步最新的远程更改,避免潜在的复杂冲突。

5.3 理解合并策略

Git 有多种合并策略(如 recursive, resolve, octopus 等),默认情况下使用 recursive。对于大多数用户,知道默认策略就足够了

5.4 合并 vs. 变基

git mergegit rebase 都是集成更改的工具,但哲学不同。合并保留了历史的完整性,而变基通过重写历史来创造一条线性的历史。在公共分支上,通常建议使用合并;在个人特性分支上,可以使用变基来保持清晰。

6. 补充信息

一个典型的 Git Flow 或 GitHub Flow 中,git merge 的使用场景:

1.特性开发:你在 feature/my-feature 分支上开发新功能。
2.准备合并:功能完成后,你切换回主分支 maindevelop
3.获取最新代码git pull origin main (这本身也是一次合并)。
4.合并特性git merge --no-ff feature/my-feature
5.解决冲突:如果存在,则手动解决。
6.推送git push origin main

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐