冲突标记 merge、diff3、zdiff3 有什么区别?这篇用同一个冲突、三种样式并排看清,再看 checkout --conflict、combined diff、rebase 时 ours/theirs 调转,以及 log --merge 怎么帮你找相关的提交。
$ git merge theirs >/dev/null 2>&1; sed -n 3,12p f.txt 第 3 行 <<<<<<< HEAD 第 4 行 ours 的修改 ======= 第 4 行 theirs 的修改 >>>>>>> theirs 共同新增的一行 第 5 行 第 6 行 第 7 行
默认样式只有 ours 和 theirs 两段。两边完全相同的开头或结尾行已经被挪到冲突块外面。
$ git merge theirs >/dev/null 2>&1; sed -n 3,12p f.txt 第 3 行 <<<<<<< HEAD 第 4 行 ours 的修改 共同新增的一行 ||||||| 01b0b82 第 4 行 ======= 第 4 行 theirs 的修改 共同新增的一行 >>>>>>> theirs
多出 ||||||| 一段,显示基础版本,便于看出两边各自的改动。缺点是共同的行被重复写进两侧,块更长。
$ git merge theirs >/dev/null 2>&1; sed -n 3,12p f.txt 第 3 行 <<<<<<< HEAD 第 4 行 ours 的修改 ||||||| 01b0b82 第 4 行 ======= 第 4 行 theirs 的修改 >>>>>>> theirs 共同新增的一行 第 5 行
在 diff3 基础上把两边共同的行挪出冲突块,块里只留真正有分歧的部分。信息量和简洁兼得,merge.conflictStyle=zdiff3 是常见的推荐配置。
$ git checkout --conflict=diff3 f.txt; grep -n -E "^(<<<<<<<|\|\|\|\|\|\|\||=======|>>>>>>>)" f.txt 4:<<<<<<< ours 7:||||||| base 9:======= 12:>>>>>>> theirs Recreated 1 merge conflict $ git checkout --conflict=merge f.txt; grep -c "^|||||||" f.txt || true 0 Recreated 1 merge conflict
git checkout --conflict=diff3 文件 用 index 里的三个阶段重新生成标记,但会覆盖你已经做的手工编辑。重新生成的标签是 ours / base / theirs。
$ git diff | sed -n 1,16p
diff --cc f.txt
index 5142d45,b88af78..0000000
--- a/f.txt
+++ b/f.txt
@@@ -1,7 -1,7 +1,11 @@@
第 1 行
第 2 行
第 3 行
++<<<<<<< HEAD
+第 4 行 ours 的修改
++=======
+ 第 4 行 theirs 的修改
++>>>>>>> theirs
共同新增的一行
第 5 行
第 6 行
$ git diff --base f.txt | grep -E "^[+-][^+-]" | head -4; echo "--- --ours:"; git diff --ours f.txt | grep -E "^[+-][^+-]" | head -4; echo "--- --theirs:"; git diff --theirs f.txt | grep -E "^[+-][^+-]" | head -4
-第 4 行
+<<<<<<< HEAD
+第 4 行 ours 的修改
+=======
--- --ours:
+<<<<<<< HEAD
+=======
+第 4 行 theirs 的修改
+>>>>>>> theirs
--- --theirs:
+<<<<<<< HEAD
+第 4 行 ours 的修改
+=======
+>>>>>>> theirs冲突期间 git diff 输出 diff --cc,每行前面两列分别表示相对 ours 与 theirs 的变化;--base、--ours、--theirs 分别与 stage 1/2/3 比较。
$ git rebase main 2>&1 | head -2; sed -n 4,10p f.txt Rebasing (1/1) Auto-merging f.txt CONFLICT (content): Merge conflict in f.txt <<<<<<< HEAD 第 4 行 ours 的修改 ======= 第 4 行 theirs 的修改 >>>>>>> 8008ba9 (我的提交) 共同新增的一行 第 5 行
rebase 是把你的提交一个个重放到新基础上,所以冲突标记里 HEAD 一侧是新基础(上游),另一侧才是你的提交。--ours/--theirs 的含义也因此颠倒。
$ git log --merge --oneline --left-right | sed -E "s/^(.)[0-9a-f]{7} /\1 /"
< 26e6c7d ours
> 94d02b5 theirsgit log --merge --left-right 只列出触及冲突文件、两边各自的提交,快速定位谁改了什么。