Git基础篇(十二)——Git解决冲突
Git基础篇(十二)——Git解决冲突
前言:
Git是多分支开发的,当然也是多人协作开发的,因此在实际的开发修改中时常会出现冲突,冲突不可怕,重要的是找到冲突的原因和解决冲突。
1 冲突的原因
冲突的产生可以分为两种。
- 分支合并冲突;
- 合并的分支对相同文件进行了不同的修改;
- 分支推送冲突;
2 关于分支合并冲突
要了解为什么分支合并会产生冲突,我们最好从实际运用场景中看哪些情况会冲突,哪些情况合并分支不会冲突。
2.1 不冲突情况
2.1.1 合并的分支新增了其他分支没有的文件
如果A分支中新增了文件a.c,而B分支中增加了b.c文件,此时将A分支与B分支合并,不会产生冲突。
2.1.2 合并的分支修改了不同的文件
如果A分支中修改了a.c文件内容,将b.c文件名改为bb.c,在B分支中修改了c.c文件内容,将d.c文件名改为dd.c,此时将A分支与B分支合并,不会产生冲突。
2.1.3 合并的分支来自同一个节点,其中一个分支不变
如果A和B分支都来自同一个节点,不修改A分支的情况下对B分支进行任意修改,此时将A和B分支合并,不但不会出现冲突,而且这样的合并是快速合并 Fast-forward ,也即不会为合并的分支创建一个提交记录,而是直接将A分支的指针指向B分支合并的节点。
如果A分支也进行了修改并提交,即便后来又改回去了,和B分支进行合并后虽然也不会冲突,但是由于A分支被改动过所以合并不会是Fast-forward形式,会为合并后的分支创建一个节点。
2.1.4 合并的分支对相同文件进行了相同的修改
如果合并的分支对相同的文件进行了相同的修改,那么进行分支合并时不会冲突,注意这种也不是快速合并Fast-forward。
2.1.5 合并的分支修改了不同文件的路径
假设有这样的目录结构,1/a.c,2/b.c。我们在A分支里将a.c文件移动到目录2中,在B分支里将b.c文件移动到目录1中,此时合并A和B分支,不会发生冲突。
2.1.6 合并的分支修改了相同文件的路径
这其实可以分两种情况讨论,即合并的分支将相同的文件移动到相同的路径下,或者将相同的文件移动到不同的路径下。这两种情况其实都不会发生冲突,但如果移动到不同的路径下,则合并后这些路径下都会有这个文件,这其实是一种错误操作。
2.2 冲突情况
2.2.1 合并的分支对相同文件进行了不同的修改
&emspp; 当要合并的分支对相同文件进行了不同修改,这个修改可以是文件的任意位置,合并时Git不知道应该以谁的内容为准,冲突就此出现。
我们在A分支里对文件a.c进行修改,,在B分支里也对文件a.c进行修改,但修改内容与A分支里的不同,此时将A分支和B分支合并,Git将提示存在冲突,并标记出文件中存在冲突的地方。
合并master和develop合并时,Git发现了分支中a.c文件内容不同,将会在冲突文件中替我们标记出冲突处等待我们手动修改后再次提交。
我们打开a.c文件可以看到冲突处已被标记。HEAD所指向的当前分支(master分支)中a.c文件在此处的文件内容为“master”,而要合并过来的develop分支中a.c文件在此处的文件内容为“develop”,两边内容不一致。
1 | <<<<<<< HEAD |
有了冲突,那么该如何解决冲突呢? 对冲突处的修改有四种可能 。
- A分支的提交是对的;
- B分支的提交是对的;
- A和B分支的提交都是对的;
- A和B的提交都不对;
因此针对a.c文件的内容修改也就有四种可能。 解决冲突就是直接修改冲突代码然后再次提交,修改时别忘了把Git自动添加的这些冲突标记删除调 。比如master和develop的提交都正确,我们将a.c文件改为以下。
1 | master |
重新提交后即完成冲突解决。
3 分支推送冲突
上面讲到的分支合并冲突是在本地的,一般来说它是单个用户自己遇到的冲突问题,在多人协作开发时常常会涉及到对远程仓库的版本提交,不同用户之间的提交也可能出现冲突。
3.1 冲突情况
3.1.1 存在跨版本的修改提交
本地在向远程仓库提交版本时,该版本如果是基于远程仓库最新提交的基础上进行的修改,那么提交不会出现冲突。基于远程仓库历史提交的基础上进行的修改,也即存在跨办呢的修改提交,此时会出现冲突。
一般我们在修改前会先使用 git pull
将远程仓库的最新提交拉取下来,并在最新提交基础上修改然后提交新记录,但多人协作时可能别人在此期间进行了新的提交,导致你的提交不是基于远程仓库的最新提交修改的,也就出现了跨版本的修改提交,如下图。
对于User B其修改是基于远程仓库的c1提交而不是最新的c2,此时User B向远程仓库提交c将会失败,那么如何解决这个冲突呢?
冲突的主要原因在于User B在本地没有c2提交记录,并且User B的新提交需要基于c2的基础上修改,因此User B此时需要做的是直接在本地执行指令 git pull
,即会将远程的提交更新到本地,并且将冲突的地方直接在冲突文件中标记出来,我们挨个解决这些冲突后再次提交即可。