my-gitbook
Blog
  • 👨‍💻简介
  • 入门教程
    • markdown 入门教程
    • git 入门教程
      • 初识 git
        • 安装 git
        • 配置 git
      • 实战 git
        • 本地仓库
        • 版本管理
        • 回到过去
        • 基本概念
        • 版本控制
        • 撤销更改
        • 删除文件
        • 远程仓库
        • 分支管理
          • 分支总览
          • 冲突合并
          • 分支策略
          • 紧急修复
          • 变基合并
          • 协同开发
          • 本地和远程仓库的本质
        • 里程碑式标签
      • 私人定制
        • 忽略文件
        • 同步推送多Git仓库
      • 搭建私服
      • 扩展工具
        • git bash 常见命令
        • git bash 朋友圈
        • git bash 扩展tree命令
        • git bash 扩展命令(上)
        • git bash 扩展命令(中)
        • git bash 扩展命令(下)
        • git submodule 父子模块
      • 沙海拾贝
        • 知识速查
        • 备忘录[译]
    • github 入门教程
      • github 访问速度太慢
      • github 徽章从何而来
    • gitbook 入门教程
      • 准备阶段
        • 前置知识
        • 环境要求
      • 快速体验
        • gitbook-cli 命令行操作
        • gitbook-editor 编辑器操作
        • gitbook.com 官网操作
      • 高级进阶
        • 插件介绍
          • 实用插件
          • 主题插件
          • 开发插件
        • 导出电子书
        • 发布电子书
      • 公众号引流
      • 优化搜索
      • 常见问题
        • 热加载失败治标之法
        • 初始化默认折叠效果
      • 参考更多
  • 编程笔记
    • java 学习笔记
    • go 学习笔记
    • php 学习笔记
    • python 学习笔记
      • 入门教程
        • 00-ubuntu安装
        • 01-Linux基础
        • 操作系统的发展史(科普章节)
      • Django教程
        • Django 学习笔记
    • Linux 学习笔记
      • Linux基础
      • Linux全栈运维
  • 兴趣开发
    • 从零开始搭建服务器
      • 从登录服务器开始
      • 更加优雅地部署项目
      • 跟着官方体验 Docker
      • 快速尝鲜基于 Docker 部署项目
      • 利用阿里云 OSS部署静态网站
      • 免费实现https访问网站
      • webhook
    • 运维部署
      • docker 环境
      • docker 操作
      • docker compose
      • docker + nginx
      • docker + blog
      • docker + resume
      • docker + gitbook
      • docker + Bark
      • docker + py12306
      • docker + mojo-Weixin
      • docker + wechat-work-message-push-go
      • docker + email
      • docker + mysql
      • docker + springboot
      • docker + redis
      • docker + gogs
      • docker + gitlab
      • docker + gitea
      • docker + crawlab
    • 工具资源
      • 给 mac 装个 vmware 虚拟机
        • 给 mac 虚拟机装个 windows
        • 给 mac 虚拟机装个 centos
        • 给 mac 虚拟机装个 ubuntu
      • 给 windows 装个 vmware 虚拟机
        • 给 windows 虚拟机装个 mac
        • 给 windows 虚拟机装个 windows
        • 给 windows 虚拟机装个 centos
        • 给 windows 虚拟机装个 ubuntu
      • 公众号历史文章备份
        • Ryen
        • 苏生不惑
        • Python技术
      • 学会开发专属 chrome 插件
      • 攻克 12306 前端加密算法
    • 如何写作
      • markdown 和富文本
      • markdown 转富文本
      • csv 半手动数据统计
      • js 半手动数据统计
      • 简述优选文章统计
      • 快速上手Mermaid流程图
      • 常见问题
  • 读书观感
    • 大数据浪潮之巅:新技术商业制胜之道
  • 程序人生
    • 待完成清单
      • yarn快速入门
      • gulp快速入门
      • nvm快速入门
      • lodash快速入门
      • regexper快速入门
      • sublime快速入门
      • github 快速入门
      • svn 快速入门
      • java 快速入门
      • mysql 快速入门
      • maven 快速入门
      • tomcat 快速入门
      • gitignore 快速入门
      • android studio 快速入门
      • npm 快速入门
      • nginx 快速入门
    • 其他
      • 重装开发环境
      • 钉钉签到提醒
      • 倒计时提醒
      • 关注网站
      • 转型之路
      • 历史统计
      • 关于作者
      • 捐赠支持
由 GitBook 提供支持
在本页
  • 背景
  • 小结

这有帮助吗?

在GitHub上编辑
  1. 入门教程
  2. git 入门教程
  3. 实战 git
  4. 分支管理

冲突合并

上一页分支总览下一页分支策略

最后更新于1年前

这有帮助吗?

如果足够幸运的话,团队成员互不影响,彼此相安无事,大家各自基于 master 分支的某个 commit 创建自己的分支,平时在分支上独立工作,等到一段时间后再合并 merge 到 master 分支,这样一样 master 作为各个功能的集大成者,最终完成项目.

然而事情总不是一帆风顺的,团队协作时由于意见不同,遇到冲突简直是家常便饭,既然无法回避冲突,当冲突发生时如何应该呢?

背景

基于 master 分支上的某个 commit ,新功能由此继续开发:

echo "git commit c1" >> test.txt
$ git add test.txt
$ git commit -m "git commit c1"

新功能分支命名为 feature ,使用git checkout -b <name> 创建分支并切换:

$git checkout -b feature
Switched to a new branch 'feature'
$ 

在新功能 feature 分支上开发新功能,并提交:

$ echo "git commit c2" >> test.txt
$ git add test.txt
$ git commit -m "git commit c2"
[feature 0fe95f8] git commit c2
 1 file changed, 1 insertion(+)
$ 

无论新功能 feature 是否开发完毕,团队的其他成员均有可能处于 master 分支并做相应更改:

$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 3 commits.
  (use "git push" to publish your local commits)

其他成员对新功能有着自己的看法,于是也提交了版本,由于我们之前提交的是 git commit c2,而此时master 分支提交的是git commit c3,显然我们两个人的意见不一致!

$ echo "git commit c3" >> test.txt
$ git add test.txt
$ git commit -m "git commit c3"
[master 0949cc3] git commit c3
 1 file changed, 1 insertion(+)
$ 

正在此时,feature 分支的新功能已开发完毕并主动切换回 master 分支,准备合并 feature 分支.

# 合并 feature 分支
$ git merge feature
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
Automatic merge failed; fix conflicts and then commit the result.
$

由于项目成员沟通不畅或者意见不一致,导致了代码冲突,git 作为版本控制系统,自然无法解决这类问题,总不能擅自做主抛弃后来的更改吧或者抛弃分支更改?所以 git 只负责抛出问题,等待我们程序员去解决问题.

既然是人的问题,那我们看一下我们到底是哪里不一致,为什么会产生冲突?

# 查看状态
$ git status
On branch master
Your branch is ahead of 'origin/master' by 4 commits.
  (use "git push" to publish your local commits)

You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)

    both modified:   test.txt

no changes added to commit (use "git add" and/or "git commit -a")
# 比较差异
$ git diff 
diff --cc test.txt
index 6e00f87,0f95fd7..0000000
--- a/test.txt
+++ b/test.txt
@@@ -3,4 -3,4 +3,8 @@@ see https://gitbook.prlrr.com/gi
  learn git branch
  see https://gitbook.prlrr.com/git/usage/branch-overview.html
  git commit c1
++<<<<<<< HEAD
 +git commit c3
++=======
+ git commit c2
++>>>>>>> feature

和我们预期一样,test.txt 文件产生了冲突,当前 HEAD 指向的提交即 master 分支是 git commit c3 ,而 feature 分支是 git commit c2,对于同一个文件的同一行内容发生不同的更改,git 不知道也不应该知道如何处理.

# 查看内容
$ cat test.txt
add test.txt
see https://gitbook.prlrr.com/git/usage/remote-repository.html
learn git branch
see https://gitbook.prlrr.com/git/usage/branch-overview.html
git commit c1
<<<<<<< HEAD
git commit c3
=======
git commit c2
>>>>>>> feature

git 用 <<<<<<< 标记一个分支冲突开始,======= 标记分支分割线,>>>>>>> 标记另一个分支结束.

经过冲突双方的讨论后,彼此间达成妥协,决定修改成git commit c2 and c3 ,修改后继续提交:

# 编辑冲突文件,按照协商一致的内容修改文件
$ vim test.txt
# 将冲突内容更改为 git commit c2 and c3
$ cat test.txt
add test.txt
see https://gitbook.prlrr.com/git/usage/remote-repository.html
learn git branch
see https://gitbook.prlrr.com/git/usage/branch-overview.html
git commit c1
git commit c2 and c3
$ git add test.txt
$ git commit -m "fix conflict"
[master 3b8f434] fix conflict

冲突已经解决,现在回顾一下提交历史,使用git log --graph 图形化展示提交历史:

# 查看提交日志
$ git log --pretty=oneline --graph
*   3b8f434013caa8c27fade4c59d7aa2ee2c079636 (HEAD -> master) fix conflict
|\  
| * 0fe95f871b371834d30ea17faa82f84b7d67672b (feature) git commit c2
* | 0949cc319e099d554795d03c69ee38923af00d6c git commit c3
|/  
* 5c482cd9965b9dfd4f273b43b240ed7db66167a8 git commit c1
* 413a4d1d2aab5ab85b6097d4b9f81cb5601c3b26 see https://gitbook.prlrr.com/git/usage/branch-overview.html
* 9c30e50248b773e38b032477a859e87abe7c1bb0 learn git branch
* b3d8193bbcb9f76c47e831e3e212f2405ae09f93 (origin/master, origin/HEAD) see https://gitbook.prlrr.com/git/usage/remote-repository.html
* 8e625640348a47ac922409a1ecb4c844385582aa add test.txt
* 9b196aab5bc87eeb11709c9eef35fca283e05c61 Initial commit
$ 

最后,删除新功能分支 feature ,不用的分支及时清理干净,需要时再创建分支.

$ git branch -d feature

小结

  • 无法杜绝冲突的发生,代码上的冲突本质上是人为因素造成的冲突.

  • 解决冲突需要有关双方协商解决,不可能独自解决冲突,除非你抛弃自我,完全以对方为准.

  • 使用 git log --graph 命令可以图表化查看提交历史,抑或 git log --pretty=oneline --graph

git-commit-c1.png
git-checkout-feature.png
git-commit-c2.png
git-checkout-master-c1.png
git-commit-c3.png
git-merge-with-conflict.png