Skip to content
On this page

Git 合并策略

合并是Git中将不同分支的更改整合到一起的重要操作。本章详细介绍各种合并策略、应用场景和最佳实践。

合并基础

什么是合并

合并是将一个分支的更改集成到另一个分支的过程。Git提供了多种合并策略来处理不同的场景。

合并类型

Git支持多种合并方式,每种都有不同的用途和效果:

  • 快进合并(Fast-forward):当目标分支没有新提交时
  • 三方合并(Three-way merge):当两个分支都有新提交时
  • Squash合并:将多个提交压缩为一个
  • Rebase合并:重新应用提交到新基底

快进合并

快进合并原理

当要合并的分支是目标分支的直接上游时,Git会执行快进合并,只是简单地移动分支指针。

bash
# 演示快进合并
# 当前在main分支,feature分支是main的直接上游
git checkout main
git merge feature-branch
# 结果:main分支指针直接移动到feature-branch的最新提交

# 查看合并结果
git log --oneline --graph

强制非快进合并

bash
# 即使可以快进也创建合并提交
git merge --no-ff feature-branch

# 配置默认行为
git config --global merge.ff false  # 总是非快进
git config --global merge.ff only   # 只允许快进

三方合并

三方合并原理

三方合并使用三个提交:两个分支的最新提交和它们的共同祖先。

bash
# 当两个分支都有独立的提交时,Git执行三方合并
git checkout main
git merge feature-branch

# Git会:
# 1. 找到共同祖先提交
# 2. 比较两个分支的更改
# 3. 自动合并更改(如果无冲突)
# 4. 创建合并提交

合并冲突

当两个分支修改了同一文件的同一部分时,会产生合并冲突。

bash
# 执行合并
git merge feature-branch

# 如果有冲突,Git会报告:
# CONFLICT (content): Merge conflict in filename.txt
# Automatic merge failed; fix conflicts and then commit the result.

# 查看冲突状态
git status

# 冲突文件会包含冲突标记:
# <<<<<<< HEAD
# 当前分支的内容
# =======
# 要合并分支的内容
# >>>>>>> feature-branch

合并策略详解

Recursive策略(默认)

bash
# 默认的合并策略,适用于两个头的合并
git merge -s recursive feature-branch

# Recursive策略的选项:
# -X ours:冲突时选择当前分支的版本
git merge -s recursive -X ours feature-branch

# -X theirs:冲突时选择要合并分支的版本
git merge -s recursive -X theirs feature-branch

# -X patience:使用耐心差异算法
git merge -s recursive -X patience feature-branch

# -X ignore-space-change:忽略空白字符差异
git merge -s recursive -X ignore-space-change feature-branch

Octopus策略

bash
# 用于合并多个分支(两个以上)
git merge -s octopus branch1 branch2 branch3

# 通常用于合并多个主题分支

Ours策略

bash
# 合并时保留当前分支内容,忽略被合并分支的更改
git merge -s ours feature-branch

# 这种合并不会产生实际更改,但会创建合并提交

高级合并技巧

Squash合并

bash
# 将feature分支的所有提交压缩为一个提交合并到main
git checkout main
git merge --squash feature-branch

# 提交squash后的更改
git commit -m "Add feature from feature-branch"

# 删除功能分支
git branch -d feature-branch

合并特定提交

bash
# 樱桃拣选(选择性合并特定提交)
git checkout main
git cherry-pick commit-hash

# 樱桃拣选多个提交
git cherry-pick commit1 commit2 commit3

# 樱桃拣选提交范围
git cherry-pick start-commit^..end-commit

# 樱桃拣选时禁用提交信息编辑
git cherry-pick -n commit-hash

合并预览

bash
# 预览合并结果而不实际执行合并
git merge --no-commit --no-ff feature-branch

# 检查合并结果
git diff --cached

# 如果不满意,可以重置
git reset --hard

# 或者完成合并
git commit -m "Merge feature-branch"

变基(Rebase)合并

基本变基

bash
# 将当前分支的提交重新应用到目标分支上
git checkout feature-branch
git rebase main

# 然后切换到main并快进合并
git checkout main
git merge feature-branch

交互式变基

bash
# 交互式变基,可以修改、重排、删除提交
git rebase -i HEAD~3

# 这会打开编辑器,显示最近3个提交:
# pick abc1234 First commit
# pick def5678 Second commit
# pick ghi9012 Third commit

# 可以修改操作:
# pick:保留提交
# reword:修改提交信息
# edit:修改提交内容
# squash:合并到前一个提交
# fixup:合并到前一个提交(丢弃提交信息)
# drop:删除提交

变基冲突处理

bash
# 变基过程中遇到冲突
git rebase --continue    # 解决冲突后继续
git rebase --abort       # 放弃变基
git rebase --skip        # 跳过当前提交

合并最佳实践

合并前的准备

bash
# 合并前确保主分支是最新的
git checkout main
git pull origin main

# 确保功能分支基于最新主分支
git checkout feature-branch
git rebase main

# 解决可能的冲突
# 测试代码确保功能正常
npm test  # 或其他测试命令

合并提交信息

bash
# 编写好的合并提交信息
git merge -m "Merge pull request #123 from user/feature-branch

Feature: Add user authentication

- Implement login functionality
- Add password validation
- Fix security vulnerabilities" feature-branch

合并后清理

bash
# 合并完成后删除功能分支
git branch -d feature-branch  # 本地删除
git push origin --delete feature-branch  # 远程删除

# 推送合并结果
git push origin main

合并工具和配置

配置合并工具

bash
# 配置外部合并工具
git config --global merge.tool vimdiff
git config --global merge.tool meld
git config --global merge.tool bc3  # Beyond Compare

# 查看配置
git config --get merge.tool

合并策略配置

bash
# 设置默认合并策略
git config --global pull.rebase false  # 使用merge
git config --global pull.rebase true   # 使用rebase

# 设置合并时的默认选项
git config --global merge.conflictstyle diff3

合并钩子

bash
# .git/hooks/post-merge
#!/bin/sh
# 合并后执行的脚本

# 更新子模块
git submodule update --init --recursive

# 安装依赖
npm install

# 运行测试
npm test

合并冲突解决

手动解决冲突

bash
# 1. 找到冲突文件
git status

# 2. 编辑冲突文件,移除冲突标记
# 3. 选择要保留的内容

# 4. 标记冲突已解决
git add conflicted-file.txt

# 5. 完成合并
git commit

使用工具解决冲突

bash
# 使用配置的合并工具
git mergetool

# 使用特定工具
git mergetool --tool=vimdiff

冲突解决策略

bash
# 查看冲突的详细信息
git diff

# 查看双方的更改
git diff --ours
git diff --theirs

# 查看共同祖先的版本
git diff --base

特殊合并场景

合并大项目

bash
# 为大项目配置更大的缓冲区
git config --global http.postBuffer 524288000  # 500MB

# 使用稀疏检出合并特定目录
git config core.sparseCheckout true
echo "specific/directory/" > .git/info/sparse-checkout

合并二进制文件

bash
# 配置二进制文件的合并策略
git config merge.binary.driver "cp %B %A"  # 保留目标分支版本
git config merge.binary.driver "cp %T %A"  # 保留合并结果

通过掌握这些合并策略和技巧,你可以在不同场景下选择最适合的合并方式,确保代码质量和开发效率。