解决合并冲突
合并冲突的产生原因
Git合并冲突通常发生在两个分支对同一文件的同一部分进行了不同修改时。当Git无法自动决定保留哪个修改时,就会产生冲突。常见场景包括:
- 两个分支修改了同一文件的同一行
- 一个分支删除了文件,另一个分支修改了该文件
- 二进制文件的合并(Git无法自动合并二进制文件)
// 分支A的修改
function add(a, b) {
return a + b;
}
// 分支B的修改
function add(a, b) {
console.log('Adding numbers');
return a + b;
}
识别合并冲突
当执行git merge
或git pull
时,如果出现冲突,Git会明确提示:
CONFLICT (content): Merge conflict in file.js
Automatic merge failed; fix conflicts and then commit the result.
冲突文件会被Git标记,包含特殊格式的冲突标记:
<<<<<<< HEAD
// 当前分支的代码
=======
// 要合并分支的代码
>>>>>>> branch-name
解决合并冲突的基本步骤
- 使用
git status
查看哪些文件有冲突 - 打开冲突文件,找到冲突标记
- 决定保留哪个修改,或进行手动合并
- 删除冲突标记(<<<<<<<, =======, >>>>>>>)
- 使用
git add
将解决后的文件标记为已解决 - 使用
git commit
完成合并
手动解决冲突的详细方法
文本文件冲突解决
对于简单的文本冲突,可以直接编辑文件:
// 冲突状态
<<<<<<< HEAD
function greet() {
return "Hello";
}
=======
function greet() {
return "Hi there";
}
>>>>>>> feature-branch
// 解决后
function greet() {
return "Hello there";
}
使用图形化工具
Git支持多种图形化合并工具:
git mergetool
命令- VS Code的Git集成
- SourceTree等第三方工具
git config --global merge.tool vscode
git mergetool
高级冲突解决技巧
接受特定版本的修改
可以完全接受某一方的修改:
# 接受当前分支的修改(ours)
git checkout --ours file.js
# 接受合并分支的修改(theirs)
git checkout --theirs file.js
使用合并策略
# 递归策略(默认)
git merge -s recursive branch-name
# 我们的策略(优先采用当前分支)
git merge -s ours branch-name
# 他们的策略(优先采用合并分支)
git merge -s theirs branch-name
处理复杂冲突场景
多个冲突文件
当多个文件存在冲突时,可以批量处理:
# 查看所有冲突文件
git diff --name-only --diff-filter=U
# 使用sed批量接受我们的修改
git diff --name-only --diff-filter=U | xargs sed -i '/^<<<<<<< /,/^>>>>>>> /d'
二进制文件冲突
二进制文件需要手动决定保留哪个版本:
# 保留当前分支版本
git checkout --ours image.png
# 或保留合并分支版本
git checkout --theirs image.png
撤销合并操作
如果合并出现问题,可以撤销:
# 合并尚未提交时
git merge --abort
# 合并已提交时
git reset --hard ORIG_HEAD
预防合并冲突的最佳实践
- 频繁合并主分支到特性分支
- 保持小规模的提交
- 使用
git pull --rebase
代替普通pull - 团队统一代码风格
- 使用
.gitattributes
文件配置合并策略
# .gitattributes示例
*.js merge=union
*.png binary
自动化合并工具
可以配置自定义合并驱动程序:
# .git/config
[merge "filfre"]
name = Feel-free merger
driver = filfre %O %A %B %L %P
recursive = binary
处理子模块冲突
子模块冲突需要特殊处理:
# 更新子模块到指定提交
git submodule update --init --recursive
# 在子模块目录中解决冲突
cd submodule-dir
git checkout desired-commit
cd ..
git add submodule-dir
合并时忽略空白字符
空白字符常导致不必要冲突:
git merge -Xignore-all-space branch-name
git merge -Xignore-space-change branch-name
使用三方合并基础
理解合并基础有助于解决复杂冲突:
# 查看合并基础
git merge-base HEAD branch-name
# 比较变化
git diff $(git merge-base HEAD branch-name) branch-name
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
下一篇:分支管理策略