git权威指南总结七:gitmerge冲突解决
git pull拉回操作中的合并
在前⾯⼀个博客,我们将到了⾮快进式推送的⾮强制性的另⼀种解决办法,那就是先拉回在提交,这⾥的拉回其实包含了两个操作:获取远程仓库的数据,将本地数据进⾏合并。可以这样写:git pull = git fetch + git merge
git merge命令⽤于合并分⽀,它的命令⾏格式为:git merge [] <commit>...⼤多数情况下的合并我们只需要提供⼀个commit分⽀就可以了,默认将指定分⽀合并到当前分⽀中。合并后的提交以当前分⽀的提交作为第⼀个⽗提交,以为第⼆个⽗提交,合并操作也⽀持多个与当前⼯作分⽀进⾏合并
默认情况下,合并后的结果会⾃动提交,我们可以通过设置选项来指定⼿动提交,通过命令:git merge --no-commit <commit>...模式可以指定合并先将结果放⼊暂存区,让⽤户⼿动对合并结果进⾏检查、更改,然后⼿动提交
合并操作并⾮总会成功,下⾯将详细介绍
合并⼀:⾃动合并
这⼀类合并不会报错,不需要⽤户来处理相应的错误,主要分为三种
修改不同的⽂件
如果两个(或者多个,这⾥只介绍两个)⽤户user1/user2各⾃的本地提交中修改的是不同的⽂件,那么第⼆次进⾏合并推送的提交将能正确合并并提交,不会遇到任何⿇烦
修改相同⽂件的不同区域
⾸先需要说明的是,⽂件的修改是分区域的,可以具体到修改哪⼀⾏,通过命令cat > fileName.suffix进⾏逐⾏修改
当user1⽤户修改了⽂件的第⼀⾏第⼆⾏并进⾏提交与上游推送,然后user2⽤户同样修改了⽂件,不过修改的是第三⾏和第四⾏,然后在进⾏git pull命令,同样能正常合并,不会遇到任何⿇烦
同时更改⽂件名和⽂件内容
如果user1⽤户将⽂件移动到了⽂件并删除(重命名的操作),并且进⾏了提交与上游推送,此时user2⽤户使⽤命令git pull获取并合并信息之后,会发现它同样也能正常合并,然后我们进⾏推送:git push origin master然后成功推送,接着我们查看⼀下远程仓库的内容,会发现git对这种情况的处理⽅式是:user2⽤户最终修改的是user1⽤户对应重命名后的⽂件
这种情况下的⾃动合并其实是有逻辑冲突的,就C语⾔编程我们来举⼀个例⼦:我们在main.c⽂件中调⽤了⼀个头⽂件head.h⽂件,然后另⼀个⽤户将该⽂件该名成head2.h⽂件,最终我们使⽤main.c⽂件将会编译错误:不到head.h头⽂件。所以在这种情况下,我们要慎重合并,或者在本次提交操作上添加⼀些重要的注释
合并⼆:冲突解决
当两个⽤户同时修改同⼀个⽂件的相同区域的内容时,就会发⽣冲突事件了。看如下例⼦:
⾸先为了保证两个⽤户的本地版本库和远程版本库⼀直,分别进⾏命令:git pull
然后先将user1⽤户修改⽂件成如下内容并进⾏提交:
然后user2⽤户进⾏同样的修改操作如下:
接下来我们进⾏user2⽤户的⾮快进式合并推送,会发现合并失败:
这就是因为两个⽤户同时修改了相同⽂件的相同区域造成的冲突,通过命令查看当前状态,会发现输出的⽇志告诉我们同时修改了⼀个⽂件
接下来我们通过⼀个命令来查看到底是哪些⽂件发⽣了合并冲突,这个命令是:git ls-files -s,该命令输出的第⼆列的值如果为0表⽰对应的⽂件没有冲突,合并成功,如果不为0,则表⽰产⽣了合并的冲突,其中具体的值对应的意义是:1表⽰两个⽤户之前⼀个共同版本的对应⽂件内容;2表⽰当前⽤户对应的⽂件版本;3表⽰合并后的⽂件对应的远程版本
通过命令:git show :n:filename查看对应⽂件的对应版本的内容
在知道了三个版本的⽂件内容之后,我们就可以⼿动的对冲突的⽂件进⾏⼿动修改操作了。这⾥需要注意的是,对应的冲突⽂件的内容已经发⽣了改变,⾥⾯对应的冲突区域的内容将会同时存在当前分⽀的内容和远程版本的内容,如下图。我们可以⼿动对该⽂件进⾏修改操作,然后在⼿动add、commit、push就可以了
然后我们通过之前的查看版本区别的命令就可以看到对应的冲突⽂件已经没有冲突了
对于上⾯的⽂件冲突,除了通过使⽤命令git ls-files -s // git show :n:filename来解决之外,还可以通过git内置的图形化界⾯⼯具来操作,通过命令:git mergetool打开⼯具,默认git提供的是kdiff3,其中上⽅的三个界⾯从左到右依次为:两个版本的前⼀个共同版本的⽂件版本、当前本地版本的⽂件版本、合并后的⽂件版本
合并三:树冲突
如果⼀个⽤户将某个⽂件进⾏改名,⽽另⼀个⽤户也对该⽂件进⾏改名,当这两个⽤户的提交进⾏合并操作时,就会发⽣树冲突,因为git⽆法替⽤户做选择。下⾯将对树冲突进⾏测试并给出解决办法
同样为了确保两个⽤户的当前版本信息和远程版本⼀直,分别对两个⽤户执⾏命令:git pull
⾸先user1⽤户将⽂件改名成
git使用详解
然后进⾏提交
接下来user2⽤户对相同的⽂件进⾏改名成
然后进⾏user2⽤户推送后提交
然后发现合并出现了冲突,这是因为多个⽤户修改了相同的⽂件的⽂件名,查看当前分⽀的状态
我们可以通过命令:git ls-files -s查看当前版本的冲突⽂件对应的状态,其中1表⽰当前合并前的版本的⽂件对应的⽂件名,2表⽰当前分⽀的⽂件名,3表⽰合并的版本的⽂件名
同样我们知道了这些信息之后就可以进⾏⼿动修改操作了。⾸先,删除需要改名的对应的⽂件,这⾥就是删除⽂件,然后删除⽂件或者删除⽂件即可进⾏提交和上游注册了
合并策略概述
git合并操作可以指定使⽤的合并策略,默认会选择最适合的合并策略。例如:两个分⽀的合并默认使⽤recursive合并策略、两个以上分⽀的合并默认使⽤octpus合并策略。我们也可以通过传递参数来指定使⽤的合并策略,命令⾏模式为:gig merge -s 合并策略 -x 合并策略参数 <commit>...
resolve策略:只能⽤于两个分⽀的合并,这个合并策略被认为是最安全、最快的合并策略
recursive策略:只能⽤于两个分⽀的合并,两个分⽀的合并默认使⽤该策略。该策略可以使⽤选项:
ours:在遇到冲突的时候,选择当前分⽀的版本,⽽忽略远程合并过来的版本。
theirs:和ours选项相反
subtree[=path]:使⽤⼦树合并策略
octpus策略:⽤于合并两个以上分⽀的策略,该策略拒绝执⾏需要⼿动解决的复杂合并。
ours:可以⽤于任意多个分⽀的合并策略,合并的结果总是使⽤当前分⽀的内容⽽丢弃远程合并过来的版本内容
subtree:这是⼀个经过调整后的recursive策略,⼦树合并策略相关内容可以去百度,这⾥就不详解了(主要是博主也不会~~)
合并相关的设置
可以通过命令git config来设置与合并相关的配置变量,对合并进⾏配置。
ge和diff3
默认的merge风格使⽤标准的冲突分界符<<<<<<<=======>>>>>>>读冲突内容进⾏标识,两个⽂字块分别是本地的修改和他⼈的修改diff3风格会在冲突⽂件中出现三个⽂字块,<<<<<<< ||||||| ======= >>>>>>>,分别表⽰本地更改版本、共同的原始版本、他⼈更改的版本l:设置执⾏命令git mergetool进⾏冲突解决时调⽤的图形化⼯具
merge..path:设置对应的图形化⼯具的安装位置
参考⽂献
git权威指南⼀书

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。