在实际的开发过程中,git冲突想必是很常见的事情,一些代码冲突可以通过进入文本编辑器,逐个手动解决冲突。但是对于rebase或者merge产生的冲突,涉及到很多文件,而且这类冲突一般是一道只保留一方的选择题。所以逐个手动解决这类冲突不太现实。
于是这今天这两位助手:--ours
和--theirs
。这两个命令适用于both added、both deleted、both modified等类型的冲突,通过这两个助手完整保留某一方的修改,而不用进入到文本编辑器逐行解决冲突。
在介绍两类助手之前,我们先回顾一下git rebase
,git merge
两类合并方式。
git merge和git rebase
假设在master主分支的基础上,有两个分支branch_a
和branch_b
,并在各自的分支上有一些提交,当前指向的分支为branch_a
,如图所示。
执行merge命令git merge branch_b
之后,分支的状态如下图所示。执行rebase命令git rebase branch_b
之后,分支的状态如下。
git merge会抽取两个分支上新增的提交,并将其合并在一起,产生一个新的提交D,生成的D节点有两个父节点。其中在合并的过程中可能会发生冲突。
git rebase会以branch_a
为参照,提取branch_b
分支上的提交,将这些修改作用在branch_a
分支上,最终结果不会产生新的提交节点。其中在将提取的修改作用在branch_a
的过程中可能会发生冲突。
以我个人的经验,在开发过程中很少应用git merge
合并代码,更常用的是git rebase
。此外在开发过程中,经常使用git rebase
命令获取master主分支的最新提交代码,在完成个人的开发任务之后,也需要rebase master分支上的代码才能申请 Pull Request,自动合并。
使用ours与theirs解决冲突
在上述两种合并中,都可能会产生冲突,需要通过手动解决。如果想要保留两个分支中的某一个可以使用git chekout --ours <fileName>
或者git checkout --theirs <fileName>
,这里需要注意的是,一定要知道哪个分支对应ours
或theirs
。
直接说结论,对于merge
和rebase
来说,这两个选项对应的分支正好是相反的。以上述示例项目为例。在使用 merge 时,ours
指的是当前分支,即branch_a
,theirs
指的是要被合并的分支,即branch_b
。而在 rebase 的过程中,theirs
指的是当前分支,即branch_a
,ours
指向修改参考分支,即branch_b
。
这么容易混淆的概念记不住? 没关系,我个人还有另一个比较直观的办法,就是直接查看冲突文件中的冲突标记。在进入冲突状态后,git会将冲突的代码用<<<<<<< ======= >>>>>>>
标识出来,方便我们手动解决。在冲突标记中,=======
之前表示的是ours
分支,之后表示theirs
分支,只需要查看某一处冲突代码即可判断出要保留的分支。
<<<<<<<HEAD
<ours contents>
=======
<theirs contents>
>>>>>>>
冲突解决步骤
以git rebase
合并命令为例说明解决冲突的步骤。
$ git checkout --ours <fileName>
$ git add <fileName> //标记该冲突已解决
$ git rebase --continue
$ git status //查看当前冲突状态
- 使用
oers
或theirs
选择要保留一方的提交 - 标记冲突已解决
- 使用
--continue
继续执行rebase - 查看冲突状态
在解决冲突过程中,如果遇到某个提交记录不需要应用,可以用下面命令忽略:
git rebase --skip
使用--abort
命令可以取消本次rebase
git rebase --abort