解决 Git 合并冲突
查看【Git】专题可浏览更多内容
场景一:不同人修改了不同文件
假设 A 与 B 两人协作开发,A 修改了 A 文件并提交推送,此时当 B 修改了 B 文件(各改各的),在 B 提交后使用 git push
命令时就会遇到:
! [rejected] dev -> dev (fetch first)
error: 无法推送一些引用到 'https://example.com/git-repo.git'
提示:更新被拒绝,因为远程仓库包含您本地尚不存在的提交。这通常是因为另外
提示:一个仓库已向该引用进行了推送。再次推送前,您可能需要先整合远程变更
提示:(如 'git pull ...')。
提示:详见 'git push --help' 中的 'Note about fast-forwards' 小节。
此时查看状态:
git status
位于分支 dev
您的分支和 'origin/dev' 出现了偏离,
并且分别有 1 和 1 处不同的提交。
(使用 "git pull" 来合并远程分支)
无文件要提交,干净的工作区
解决方法
此时对于 B 来说,有一个领先于远程仓库的提交(B 文件的修改)和一个落后于远程仓库的提交(A 对 A 文件的修改)。
那么解决方法也很简单,先拉取再推送即可:
git pull
使用 git pull
后会弹出一个交互式界面:
Merge branch 'dev' of https://example.com/git-repo.git dev
# 请输入一个提交信息以解释此合并的必要性,尤其是将一个更新后的上游分支
# 合并到主题分支。
#
# 以 '#' 开始的行将被忽略,而空的提交说明将终止提交。
这里其实就是一个改动的提交信息,使用这默认信息或修改第一行为你需要的提交信息即可。
然后再进行推送:
git push
有些方法会使用 git fetch
+ git merge
,但实际上 git pull
就是两者的组合。
场景二:不同人修改了相同文件的不同部分
假设 A 与 B 两人协作开发,A 修改了文件 A 的第一行后提交并推送,而 B 修改了文件 A 的第二行,在提交后推送时,遇到提示:
! [rejected] dev -> dev (fetch first)
error: 无法推送一些引用到 'https://example.com/git-repo.git'
提示:更新被拒绝,因为远程仓库包含您本地尚不存在的提交。这通常是因为另外
提示:一个仓库已向该引用进行了推送。再次推送前,您可能需要先整合远程变更
提示:(如 'git pull ...')。
提示:详见 'git push --help' 中的 'Note about fast-forwards' 小节。
解决方法
解决方法其实和「场景一」相同,先拉取远程仓库的数据处理好再推送即可:
git pull
# 或
git fetch
git merge origin/dev # 此处示例的分支为 dev
使用 git pull
或 git merge
,Git 会将 A 的修改内容进行合并,成功后会弹出一个交互式界面:
Merge branch 'dev' of https://example.com/git-repo.git dev
# 请输入一个提交信息以解释此合并的必要性,尤其是将一个更新后的上游分支
# 合并到主题分支。
#
# 以 '#' 开始的行将被忽略,而空的提交说明将终止提交。
这里其实就是一个改动的提交信息,使用这默认信息或修改第一行为你需要的提交信息即可。
然后再进行推送:
git push
场景三:不同人修改了相同文件的相同部分
假设目前有个 Markdown 文件是这样的:
# 标题1
## 标题2
标题
#### 标题4
##### 标题5
###### 标题6
出问题的是标题3,它应该是这样的:
### 标题3
仍然假设 A 与 B 两人协作开发,A 修改成了这样:
### 标题
也就是加了井号但是没加上数字 3,然后 A 提交并推送了。
然后 B 修改成了这样:
标题3
加上了数字 3 但没加井号。
此时 B 提交后使用 git pull
会收到这样的提示:
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0
展开对象中: 100% (3/3), 301 字节 | 100.00 KiB/s, 完成.
来自 https://example.com/git-repo.git
c26a0c0..2e709cc dev -> origin/dev
自动合并 README.md
冲突(内容):合并冲突于 README.md
自动合并失败,修正冲突然后提交修正的结果。
解决方法
打开冲突文件:
# 标题1
## 标题2
<<<<<<< HEAD
标题3
=======
### 标题
>>>>>>> origin/dev
#### 标题4
##### 标题5
###### 标题6
Git 是没办法知道我们想怎么解决冲突问题的,所以它只能给予帮助提示:
- 由
<<<<<<< HEAD
开头与>>>>>>> origin/dev
结尾中间的部分是存在冲突的; =======
以上的部分是自己(B)所做的改动的部分;=======
以下的部分是来自远程仓库上,也就是 A 推送上去的改动;
最终,B 在与 A 沟通后并结合 B 自身的修改,最终 B 将文件修改如下:
# 标题1
## 标题2
### 标题3
#### 标题4
##### 标题5
###### 标题6
然后使用命令:
# 添加修正的冲突的文件
git add READMD.md
git commit -m '解决了冲突'
git push
枚举对象中: 10, 完成.
对象计数中: 100% (10/10), 完成.
使用 8 个线程进行压缩
压缩对象中: 100% (6/6), 完成.
写入对象中: 100% (6/6), 653 字节 | 653.00 KiB/s, 完成.
总共 6(差异 0),复用 0(差异 0),包复用 0
To https://example.com/git-repo.git
2e709cc..bc24593 dev -> dev
成功了,来看看提交了几次以及分支情况:
git log --graph --pretty=short
* commit bc245936278fda2b14c939b20928e7ba4877c8a6 (HEAD -> dev, origin/dev)
|\ Merge: 5aa90e7 2e709cc
| | Author: b <b@example.com>
| |
| | b:修正冲突
| |
| * commit 2e709ccd4b67b74223b2d78e4f0277d1479c6e46
| | Author: a <a@example.com>
| |
| | a:加上标题
| |
* | commit 5aa90e7507dbdcfb3931e6c87166627cd3583366
|/ Author: b <b@example.com>
|
| b:增加了数字3
|
* commit c26a0c03c534d9a277366c7c52292fb24a3d3ea2
| Author: x <x@example.com>
|
| 标题初稿
在发生共同冲突的时候,建议需要与他人协商讨论修改结果,尽可能的不要改动他人的部分,毕竟是团队协作嘛。