3.13 查找文件差异并进行修补

当一个文件有多个版本时,如果能够重点标记出这些版本之间的不同而无须通过人工查看来比较,那就简直是太棒了。如果文件有 1000 行,光靠人工进行比较可是件极其费时费力的活儿。这则攻略为你演示如何用行号对文件之间的差异进行重点标记。当多名开发人员在文件繁多的环境下工作时,如果某个人对其中某个文件进行了修改,那么应该将这个修改告知其他所有开发人员。如果发送整个源代码,不仅浪费磁盘存储空间,而且单靠手动检查这些修改就很耗时间。这时,发送一个差异文件就显得很有用了。它只包含那些被修改过、添加或删除的行以及行号。这个差异文件被称为修补文件(patch file)。我们可以用patch命令将修补文件中包含的更改信息应用到原始文件中。我们也可以再次进行修补来撤销改变。来看看如何才能实现这一切。

3.13.1 实战演练

diff命令可以生成差异文件。

为了生成差异信息,先创建下列文件。

  • 文件 1: version1.txt
  1. this is the original text
  2. line2
  3. line3
  4. line4
  5. happy hacking
  • 文件 2: version2.txt
  1. this is the original text
  2. line2
  3. line4
  4. happy hacking !
  5. GNU is not UNIX

非一体化(non-unified)形式的diff输出(在不使用 -u选项的情况下)如下:

  1. $ diff version1.txt version2.txt
  2. 3d2
  3. 6c5
  4. > GNU is not UNIX

一体化形式的diff输出如下:

  1. $ diff -u version1.txt version2.txt
  2. --- version1.txt 2010-06-27 10:26:54.384884455 +0530
  3. +++ version2.txt 2010-06-27 10:27:28.782140889 +0530
  4. @@ -1,5 +1,5 @@
  5. this is the original text
  6. line2
  7. -line3
  8. line4
  9. happy hacking !
  10. -
  11. +GNU is not UNIX

选项 -u用于生成一体化输出。因为一体化输出的可读性更好,更易于看出两个文件之间的差异,所以人们往往更喜欢这种输出形式。

在一体化diff输出中,以 + 起始的是新加入的行,以 - 起始的是删除的行。

修补文件可以通过将diff的输出重定向到一个文件来生成:

  1. $ diff -u version1.txt version2.txt > version.patch

现在就可以用patch命令将修改应用于任意一个文件。当应用于version1.txt时,我们就可以得到version2.txt;而当应用于version2.txt时,就可以得到version1.txt。

用下列命令来进行修补:

  1. $ patch -p1 version1.txt < version.patch
  2. patching file version1.txt

version1.txt的内容现在和verson2.txt的内容一模一样。

下面的命令可以撤销做出的修改:

  1. $ patch -p1 version1.txt < version.patch
  2. patching file version1.txt
  3. Reversed (or previously applied) patch detected! Assume -R? [n] y
  4. #修改被撤销

在撤销修改时,若使用patch命令的 -R选项,则不会提示用户y/n

3.13.2 补充内容

让我们再看一些diff的其他特性。

生成目录的差异信息

diff命令也能够以递归的形式作用于目录。它会对目录中所有的内容生成差异输出。

使用下面的命令:

  1. $ diff -Naur directory1 directory2

上面命令中出现的选项含义如下。

  • -N:将所有缺失的文件视为空文件。

  • -a:将所有文件视为文本文件。

  • -u:生成一体化输出。

  • -r:遍历目录下的所有文件。