在拉取时以对方更改解决 Git 合并冲突
技术背景
在使用 Git 进行版本控制时,多人协作开发或在不同分支间进行合并操作时,经常会遇到合并冲突的问题。合并冲突是指当两个或多个分支对同一文件的同一部分进行了不同的修改,Git 无法自动确定如何合并这些更改,就需要开发者手动解决冲突。本文将介绍如何在拉取时以对方的更改来解决合并冲突。
实现步骤
拉取时使用指定策略
可以使用以下命令在拉取时以对方的更改解决冲突:
1
| git pull -s recursive -X theirs <remoterepo or other repo>
|
对于默认仓库,可简化为:
已处于冲突状态
1 2
| git checkout --theirs . git add .
|
1 2
| git checkout --ours . git add .
|
处理单个冲突文件
1 2
| git checkout --theirs path/to/the/conflicted_file.php git add path/to/the/conflicted_file.php
|
1 2
| git checkout --ours path/to/the/conflicted_file.php git add path/to/the/conflicted_file.php
|
取消合并并重新拉取
如果已经处于冲突状态,且不想逐个检查路径,可以尝试:
1 2
| git merge --abort git pull -X theirs
|
忽略本地修改
如果想简单地忽略仓库中文件的任何本地修改,例如在一个应始终是远程仓库镜像的客户端上,可以运行:
1
| git fetch && git reset --hard origin/master
|
使用合并策略选项
1
| git merge [branch] --strategy-option ours
|
1
| git merge [branch] --strategy-option theirs
|
解决特定分支的所有冲突
1
| git diff --name-only --diff-filter=U | xargs git checkout ${branchName}
|
例如,在合并状态下,想保留冲突文件的 master
版本:
1
| git diff --name-only --diff-filter=U | xargs git checkout master
|
VS Code 集成 Git IDE
- 按
Ctrl + Shift + P
打开命令面板。 - 选择
Merge Conflict: Accept All Incoming
接受冲突文件中的所有传入更改。
自定义合并工具
可以在 git-config
中配置自定义合并工具,例如:
1 2
| [mergetool "ours"] cmd = "sed -i -e '/^<<<<<<</d' -e '/^=======/,/^>>>>>>>/d' -- $MERGED"
|
然后使用 git mergetool --tool=ours
调用。
Emacs smerge - mode
在 Emacs 中使用 smerge - mode
定义函数来解决所有冲突标记:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| (defun aj/smerge-keep-mine-all () "" (interactive) (save-excursion (beginning-of-buffer) (while (ignore-errors 'user-error (progn (smerge-next) t)) (smerge-keep-mine))))
(defun aj/smerge-keep-other-all () "" (interactive) (save-excursion (beginning-of-buffer) (while (ignore-errors 'user-error (progn (smerge-next) t)) (smerge-keep-other))))
|
Visual Studio 2022
- 进入“Manage Branches”,双击要将
dev
合并到的分支。 - 右键点击
dev
,选择 Merge 'dev' into 'your - branch'
。 - 若出现大量合并冲突,点击
Abort
。 - 打开
cmd
。 - 输入
git merge --strategy-option ours --no - commit dev
并回车。 - 回到 Visual Studio,输入提交信息并提交。
合并单个文件
将 master
分支合并到 development
分支,并接受 master
分支中单个特定文件的版本:
1 2 3 4 5 6
| git pull origin master git checkout --theirs path/to/foo git add path/to/foo git commit -a -m "Merge master into development branch" git pull git push
|
核心代码
使用 sed
解决冲突
1
| sed -i -e '/^<<<<<<</,/^=======/d' -e '/^>>>>>>>/d' foo
|
1
| sed -i -e '/^<<<<<<</d' -e '/^=======/,/^>>>>>>>/d' foo
|
最佳实践
- 在进行合并操作前,先确保本地仓库是最新的,可以使用
git pull
拉取最新代码。 - 对于重要的项目,建议在测试环境中先进行合并操作,确认没有问题后再推送到生产环境。
- 如果不确定要接受哪些更改,可以先使用
git diff
查看具体的差异,再做决定。
常见问题
出现 fatal: Not possible to fast - forward, aborting.
错误
可以使用以下命令拉取并接受对方更改,同时进行快进合并:
git checkout --ours/theirs
无法解决冲突
可以尝试使用 git checkout HEAD -- path/to/file
或 git checkout MERGE_HEAD -- path/to/file
,然后执行 git add .
。