Git merge 冲突解决简明教程
目录
1. 概述 1
2. 从git difftool & mergetool 工具开始 – Beyond Compare 1
2.1. 下载安装Beyond Compare 1
2.2. 创建启动Beyond Compare脚本 1
2.2.1. 创建git-difftool-bcomp-wrapper.sh 2
2.2.2. 创建git-mergetool-bcomp-wrapper.sh 2
2.3. 设置环境变量 2
2.4. 更改Git配置文件 3
2.5. difftool和mergetool实际操作 3
3. Git 分支 origin、master 介绍 3
3.1. git 分支简介 3
3.2. git diff & git difftool查看master分支和origin/master分支 4
4. Git fetch和git pull的区别 5
4.1. git fetch 5
4.2. git pull 5
4.3. git pull 和 git fetch总结 6
5. Git merge 与 Git rebase 冲突解决 6
5.1. git merge解决冲突 6
5.1.1. 冲突场景设定 6
5.1.2. 分支A的更新提交 6
5.1.3. 分之B的更新提交 6
5.1.4. B解决冲突并提交 7
5.2. git rebase 8
在用git进行源代码版本维护的时候,常常会进行各代码版本之前区别的查看,例如在每次提交改动前进行git diff 可以看到源文件代码相对相应版本或是远程仓库的改动情况,如果有冲突还需要进行merge即整合改动的代码到指定版本(例如远程分支)。
在对复杂代码版本之间进行diff时,如果没有difftool 是不可想象的,如果有一个好用并且自己比较熟悉的Compare-比较工具往往会让你事半功倍,Window下的Diff工具有很多,WinMerge(免费),Araxis Merge(收费),装了TortoiseSVN的话,也带有一个Diff工具TortioseIDiff,SourceGear MergeDiff,支持Windows,Mac,Linux,也非常好用,在这里我介绍比较常用的Beyond Compare.
下载和安装Beyond Compare工具,这里就不赘述了,网上搜搜。
在Git的安装路径的\cmd路径下创建以下两个脚本,前面的路径名为安装后的Beyond Compare.exe的实际路径名,这是为了让git能找到比较工具,例如Beyond Compare安装路径 "D:\Software_install\Beyond\Beyond Compare 3\BCompare.exe" "$1" "$2" | cat。
# place this file in the Windows Git installation directory /cmd folder
# be sure to add the ../cmd folder to the Path environment variable
# diff is called by git with 7 parameters:
# path old-file old-hex old-mode new-file new-hex new-mode
"D:\Software_install\Beyond\Beyond Compare 3\BCompare.exe" "$1" "$2" | cat
# place this file in the Windows Git installation directory /cmd folder
# be sure to add the ../cmd folder to the Path environment variable
# passing the following parameters to mergetool:
# local base remote merge_result
"D:\Software_install\Beyond\Beyond Compare 3\BCompare.exe" "$1" "$2" "$3" --result="$4" --title1="Mine"
为了让Git能找到前面定义的两个sh,需要将git安装目录的cmd路径设置为环境变量,例如我的cmd路径:C:\Program Files (x86)\Git\cmd; 如下图:
更改配置的目的就是为了指定Git的difftool和mergetool,首先找到.gitconfig文件,例如我的安装路径C:\Program Files (x86)\Git\etc,打开编辑器编辑.gitconfig文件,在文件的最后追加工具的描述, 如下:
[merge]
tool = bcomp
[diff]
tool = bcomp
[mergetool]
keepBackup = false
[mergetool "bcomp"]
cmd = git-mergetool-bcomp-wrapper.sh "$LOCAL" "$BASE" "$REMOTE" "$MERGED"
[difftool "bcomp"]
cmd = git-difftool-bcomp-wrapper.sh "$LOCAL" "$REMOTE"
以上就完成了git difftool和 mergetool的配置,下面就来试试效果。
实际操作操作在下面的章节介绍。
为了进行下一步的讲解,首先必须要有git分支的概念,废话少数,上个实例子。
在讲解之前默认你已经有了一个从远程服务器clone到本地的代码版本,这个时候你可以用git branch –a 来查看所有分支, 如下:
明白了git 中master分支和origin/master 分支的区别,我们就可以用git diff 工具查看每个版本之间的区别。
在介绍git diff 和 git difftool 操作之前,我们必须确保你本地的分支master和远程的分支(origin/master)是有差异的 - 为了达到演示效果可以人为弄些差异。
首先用git fetch origin master 抓取远程仓库 – 关于fetch和pull想写介绍下一节会详细介绍。如下:
例如下图在git bash中执行git diff命令:
由此可以看到master和origin/master之间的区别。
但是你会发现在命令行中一点一点的查看实在是太憋屈了,这下前面的配置difftool工具Beyond Compare可以派上用场了。
运行命令: git difftool master origin/master
首先提示的是第一个两个分支之间有区别的文件,键入Y;即可转到Beyond Compare中查看了两个文件的区别:
关闭这个窗口,然后回到bash,如果还有不一样的文件,也会有同样的提示,直到所有文件遍历完为止。
Git从远程的分支获取最新的版本到本地有两个命令使用的非常频繁,分别是git fetch和git pull,所以在进行merge冲突解决之前,对git fetch 和git pull命令的深入理解非常有必要。
git fetch,即从远程服务器抓取版本更新,相当于是从远程获取最新版本到本地,不会自动merge。
git log //在抓取远程更新之前,log查看当前的日志
git fetch origin master //从远程抓取更新
git log //抓取之后可以看到log日志没有更新 – 还没有merge
所以在fetch之后可以进行diff操作,即查看本地master分支和名叫origin的远程库的master分支之间进行diff,查看两个版本的不同。
也就是以下两条命令:
git diff master origin/master
git difftool master origin/master
这已经在上一章节 : git diff & git difftool查看master分支和origin/master分支 中有详细的介绍。
git pull:从远程获取最新版本并merge到本地
git pull origin master //从名叫origin的远程仓库的master分支上抓取分支并且merge
上述命令其实相当于git fetch 和 git merge
在实际使用中,git fetch更安全一些。
因为在merge前,我们可以查看更新情况,用git diff & git difftool命令查看本地master和远程master分支之间的差别,然后再决定是否合并。
为了很好的理解冲突产生和冲突解决的整个过程,下面用一个例子讲解,最后用merge解决冲突,并提交解决冲突后的更新到服务器。
首先设定一个场景:开发者A和开发者B,从远程origin上分别clone一份代码到自己工作电脑上,然后两人分别在自己的本地进行开发,然后A先提交了快照
Snapshot_A1,这个时候B也要提交代码,但是代码改动的地方和A改动的已经提交更新到服务器上的有冲突,这个时候就需要将服务器上的最新代码fetch或是
Pull到自己本地,解决冲突后再提交自己的改动到服务器。
以下来演示此过程。
A端:对文件README.md进行了以下修改:
然后A提交更改到服务器:
git commit -a -m "Added comment1 to README.md"
git push o r
另一边B,也对README.md进行了以下修改,内容如下:
并且B也进行commit和push,做了如下操作:
git commit -a -m "Added comment1 to README.md"
git push origin master
Push的时候提示有冲突,本地的版本比较老。
于是B想抓取远程服务器的更新来看一下:
git fetch origin master
发现服务器是有更新,于是B想看看服务器做了什么更新
执行命令:git difftool origin/master
发现README.md做了更新,和自己更新的文件一样,键入"Y",
通过beyond可以看到两个文件的区别了,B查看了下,改动需要整合,下一步就是要解决冲突,然后提交。
B 在bash上运行命令:
git merge origin/master
提示有冲突,git尝试自动整合,发现整合不了,需要手动解决冲突, 幸运的是
Git已经把有冲突的地方标识出来了,如下图:
其中:
把README.md修改完后,再次尝试merge,运行命令:
git merge origin/master
执行命令:
git add README.md
git commit -a -m "Merge README.md changed on B into main branch"
在执行提交:
git push origin master
发现已经提交成功。