[git] git merge 冲突解决


  1. 概述

在用git进行源代码版本维护的时候,常常会进行各代码版本之前区别的查看,例如在每次提交改动前进行git diff 可以看到源文件代码相对相应版本或是远程仓库的改动情况,如果有冲突还需要进行merge即整合改动的代码到指定版本(例如远程分支)。

 

  1. 从git difftool & mergetool 工具开始 – Beyond Compare

在对复杂代码版本之间进行diff时,如果没有difftool 是不可想象的,如果有一个好用并且自己比较熟悉的Compare-比较工具往往会让你事半功倍,Window下的Diff工具有很多,WinMerge(免费),Araxis Merge(收费),装了TortoiseSVN的话,也带有一个Diff工具TortioseIDiff,SourceGear MergeDiff,支持Windows,Mac,Linux,也非常好用,在这里我介绍比较常用的Beyond Compare.

  1. 下载安装Beyond Compare

下载和安装Beyond Compare工具,这里就不赘述了,网上搜搜。

  1. 创建启动Beyond Compare脚本

在Git的安装路径的\cmd路径下创建以下两个脚本,前面的路径名为安装后的Beyond Compare.exe的实际路径名,这是为了让git能找到比较工具,例如Beyond Compare安装路径 "D:\Software_install\Beyond\Beyond Compare 3\BCompare.exe" "$1" "$2" | cat。

  1. 创建git-difftool-bcomp-wrapper.sh

# 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

 

  1. 创建git-mergetool-bcomp-wrapper.sh

# 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"

 

  1. 设置环境变量

为了让Git能找到前面定义的两个sh,需要将git安装目录的cmd路径设置为环境变量,例如我的cmd路径:C:\Program Files (x86)\Git\cmd; 如下图:

 

  1. 更改Git配置文件

更改配置的目的就是为了指定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的配置,下面就来试试效果。

 

  1. difftool和mergetool实际操作

实际操作操作在下面的章节介绍。

 

  1. Git 分支

    origin、master 介绍

    1. git 分支简介

为了进行下一步的讲解,首先必须要有git分支的概念,废话少数,上个实例子。

在讲解之前默认你已经有了一个从远程服务器clone到本地的代码版本,这个时候你可以用git branch –a 来查看所有分支, 如下:

  • *master,*表示当前工作的分支,当前工作的分支叫做master,也就是本地分支。
  • remotes/origin/master 是一个名叫origin的远程库上的master分支,无法在本地更改其内容。
  • origin 只是一个别名,在clone完成之后,Git会自动为你将此远程仓库命名为origin(git remote –v或者查看.git/config可以看到origin的含义)。
  • remotes/origin/HEAD -> origin/master,HEAD 是一个指针,它指向名叫origin的远程库上的master分支。
  1. git diff & git difftool查看master分支和origin/master分支

明白了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,如果还有不一样的文件,也会有同样的提示,直到所有文件遍历完为止。

 

  1. Git fetch和git pull的区别

Git从远程的分支获取最新的版本到本地有两个命令使用的非常频繁,分别是git fetch和git pull,所以在进行merge冲突解决之前,对git fetch 和git pull命令的深入理解非常有必要。

 

  1. git fetch

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分支 中有详细的介绍。

 

  1. git pull

git pull:从远程获取最新版本并merge到本地

git pull origin master //从名叫origin的远程仓库的master分支上抓取分支并且merge

上述命令其实相当于git fetch 和 git merge

 

  1. git pull 和 git fetch总结

在实际使用中,git fetch更安全一些。
因为在merge前,我们可以查看更新情况,用git diff & git difftool命令查看本地master和远程master分支之间的差别,然后再决定是否合并。

 

  1. Git merge 与 Git rebase 冲突解决

    1. git merge解决冲突

为了很好的理解冲突产生和冲突解决的整个过程,下面用一个例子讲解,最后用merge解决冲突,并提交解决冲突后的更新到服务器。

  1. 冲突场景设定

首先设定一个场景:开发者A和开发者B,从远程origin上分别clone一份代码到自己工作电脑上,然后两人分别在自己的本地进行开发,然后A先提交了快照

Snapshot_A1,这个时候B也要提交代码,但是代码改动的地方和A改动的已经提交更新到服务器上的有冲突,这个时候就需要将服务器上的最新代码fetch或是

Pull到自己本地,解决冲突后再提交自己的改动到服务器。

以下来演示此过程。

  1. 分支A的更新提交

A端:对文件README.md进行了以下修改:

然后A提交更改到服务器:

git commit -a -m "Added comment1 to README.md"

git push o r

  1. 分之B的更新提交

另一边B,也对README.md进行了以下修改,内容如下:

并且B也进行commit和push,做了如下操作:

git commit -a -m "Added comment1 to README.md"

git push origin master

Push的时候提示有冲突,本地的版本比较老。

  1. B解决冲突并提交

于是B想抓取远程服务器的更新来看一下:

git fetch origin master

发现服务器是有更新,于是B想看看服务器做了什么更新

执行命令:git difftool origin/master

发现README.md做了更新,和自己更新的文件一样,键入"Y",

通过beyond可以看到两个文件的区别了,B查看了下,改动需要整合,下一步就是要解决冲突,然后提交。

B 在bash上运行命令:

git merge origin/master

提示有冲突,git尝试自动整合,发现整合不了,需要手动解决冲突, 幸运的是

Git已经把有冲突的地方标识出来了,如下图:

其中:

  • <<<<<<< HEAD部分也就是当前你的工作分支所做的修改。
  • >>>>>>> origin/master 就是远程服务器上已近有的更新。

 

把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

 

发现已经提交成功。

  1. git rebase

猜你喜欢

转载自blog.csdn.net/eternally123/article/details/79599790