diff用来比较两个文件,在开发过程中,我们免不了要和diff打交道。

  • 提交代码到版本库前,对比工作区版本和版本库中的文件的差异;
  • 某一功能的合入引发了Bug,对比没有出现Bug之前的版本记录;
  • 补丁记录,比如npm的patch-package记录修改npm包源码记录;
  • ...

bcompare对比文件.jpg

diff 格式类型

在使用diff之前,我们先了解一下diff的格式。diff有三种格式:

  • 正常格式(normal diff)
  • 上下文格式(context diff)
  • 合并格式(unified diff)

下面使用示例说明这三种文件格式,为了方便理解我们创建两个文件f1.txt,f2.txt。

f1.txt

abc
abc
abc
abc
abc
abc
abc

f2.txt

abc
abc
xby
abc
abc
abc
abc
def

f2.txt 第3行由abc改成了xby,并多了第8行def。

正常格式的diff

$ diff f1.txt f2.txt
2a3
> xby
7c8
< abc
---
> def

这里记录了两个变动,每个变动都分为变动的位置和变动的内容。这里的变动指的是,我们如何改变第一个文件才能与第二个文件相匹配。

第一个变动:

2a3
> xby

2a3表明变动的位置,前边的2表示f1.txt的第2行,后边的3表示f2.txt的第3行。中间的a是addition的缩写,表示追加,其它模式还有删除(d,代表deletion)和改变(c,代表change)。

>表示增加内容,<表示删除内容。

这里就表明f2.txt相对于f1.txt,在第2行后边增加了一行内容xby。换个说法,f1.txt在第2行后边增加一行xby就会和f2.txt一样。

第二个变动:

7c8
< abc
---
> def

中间的分割线是用来分隔f1.txt和f2.txt两个文件。

f1.txt第7行,我的理解是基于第一个变动,这里的abc在第8行,f1.txt中移除第8行abc,再增加一行def,就可以和f2.txt变成一致了。

上下文格式(context diff)

$ diff -c f1.txt f2.txt
*** f1.txt      2024-04-12 07:14:59.880577600 +0800
--- f2.txt      2024-04-12 07:51:09.259859600 +0800
***************
*** 1,7 ****
  abc
  abc
  abc
  abc
  abc
  abc
! abc
--- 1,8 ----
  abc
  abc
+ xby
  abc
  abc
  abc
  abc
! def

这个结果分成四个部分。

第一部分的两行,显示两个文件的基本信息:文件名和时间信息。

*** f1.txt      2024-04-12 07:14:59.880577600 +0800
--- f2.txt      2024-04-12 07:51:09.259859600 +0800

"***"表示变动前的文件,"---"表示变动后的文件。

第二部分是15个星号,将文件的基本信息与变动内容分割开。

***************

第三部分显示变动前的文件,即f1.txt。

*** 1,7 ****
  abc
  abc
  abc
  abc
  abc
  abc
! abc

这时不仅显示发生变化的第2行和第7行,还显示变动行的前面和后边的几行(3行)。前面的"*** 1,7 ****"就表示,从第1行开始连续7行。

另外,文件内容的每一行最前面,还有一个标记位。如果为空,表示该行无变化;如果是感叹号(!),表示该行有改动;如果是减号(-),表示该行被删除;如果是加号(+),表示该行为新增。

第四部分显示变动后的文件,即f2.txt。

--- 1,8 ----
  abc
  abc
+ xby
  abc
  abc
  abc
  abc
! def

第3行加了一行,第8行有变动。

合并格式的diff

$ diff -u f1.txt f2.txt
--- f1.txt      2024-04-12 07:14:59.880577600 +0800
+++ f2.txt      2024-04-12 07:51:09.259859600 +0800
@@ -1,7 +1,8 @@
 abc
 abc
+xby
 abc
 abc
 abc
 abc
-abc
+def

它的第一部分,也是文件的基本信息。

--- f1.txt      2024-04-12 07:14:59.880577600 +0800
+++ f2.txt      2024-04-12 07:51:09.259859600 +0800

"---"表示变动前的文件,"+++"表示变动后的文件。

第二部分,变动的位置用两个@作为起首和结束。

@@ -1,7 +1,8 @@

前面的"-1,7"分成三个部分:减号表示第一个文件(即f1.txt),"1"表示第1行,"7"表示连续7行。合在一起,就表示下面是第一个文件从第1行开始的连续7行。同样的,"+1,8"表示变动后,成为第二个文件从第1行开始的连续8行。

第三部分是变动的具体内容。

 abc
 abc
+xby
 abc
 abc
 abc
 abc
-abc
+def

除了有变动的那些行以外,也是上下文各显示3行。它将两个文件的上下文,合并显示在一起,所以叫做"合并格式"。每一行最前面的标志位,空表示无变动,减号表示第一个文件删除的行,加号表示第二个文件新增的行。

Markdown diff语法

Markdown diff语法是一种用于显示代码版本差异的Markdown语法,使用diff语法可以清晰的展示代码变化,例如代码的添加、删除、修改。在Markdown中,diff语法使用代码块的语法,需要指定编程语言为diff。

以上面合并格式语法为例:

```diff
$ diff -u f1.txt f2.txt
--- f1.txt      2024-04-12 07:14:59.880577600 +0800
+++ f2.txt      2024-04-12 07:51:09.259859600 +0800
@@ -1,7 +1,8 @@
 abc
 abc
+xby
 abc
 abc
 abc
 abc
-abc
+def
```

效果:
版本差异.jpg

可以看到显示的结果中使用颜色对diff结果的各个部分做了区分。

结语

总的来说,diff语法是一种在Markdown中用于展示代码差异的语法,它以直观的方式展示了代码的更改,使得阅读和理解代码变化更加方便和直观。