ivaneeo's blog

自由的力量,自由的生活。

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  669 Posts :: 0 Stories :: 64 Comments :: 0 Trackbacks

#

之所以称为正规(normal)格式输出是因为这种格式只显示有差别的行,不会混入任何相同的行.它称为默认得输出格式的原因是为了遵守POSIX标准.正规格式很少用于发布软件补丁,但以此为基础对理解任何一种diff的输出格式很有用处.一般来说,正规块(normal hunk)的格式如下:
  change_command
  <srcfile line
  <srcfile line
  ...
  >dstfile line
  >dstfile line
  change_command的格式如下:首先是一个来自srcfile的行号或以逗号隔开的行号范围,然后是一个命令符,接下来是一个来自dstfile的行号或以逗号隔开的行号范围.的命令符可以为:
.a--添加
.b--删除
.c--更改
posted @ 2005-08-04 17:23 ivaneeo 阅读(168) | 评论 (0)编辑 收藏

并排(side-by-side)格式虽然对于创建源代码补丁来说没有什么用处,但是用它直接比较源代码文件比较容易,因为它把srcfile和dstfile的内容并排显示在屏幕上.
ivan@debian $diff -y -W 80 hello.c howdy.c
#include <stdio.h>                    #include <stdio.h>
                                 >    #include <stdlib.h>
int main(void)                        int main(void)
{                                     {
  char msg[] = "Hello, Linux pr  |       char msg[] = "Hello, Linux pr
                                      
  puts(msg);
  printf("Here you are, using d  |  printf("Here you are, using d
                                
  return 0;                      |  exit(EXIT_SUCCESS);
}

字符">"表示该行在dstfile而不在srcfile里.类型地,字符"<"表示该行在srcfile而不在dstfile里.字符"|"标记出两个文件不相同的行.
posted @ 2005-08-04 17:22 ivaneeo 阅读(264) | 评论 (0)编辑 收藏

以前曾提到过,在发布软件补丁时很少(可能从不)使用正规和并排的块格式.但diff产生的上下文(context)或统一(unified)的块格式是创建补丁所采用的格式.为了产生上下文的差异文件(它们称为context diff的原因是它们显示出了有差别的行的上下文内容),可使用diff的-c或-C[num]选项.
  提示:和大多数GNU程序一样,diff也支持长选项,也就是以两个两字符"--"开头,后面跟着更容易记忆的名字的选项,例如,创建一个上下文diff文件的长选项是"--context=[num]".


上下文输出举例
$diff -c hello.c howdy.c
*** hello.c Web Aug 9 21:02:42 2000
--- howdy.c Web Aug 9 21:04:30 2000
*************
*** 1,12 ****
  #include <stdio.h>
  
  int main(void)
  {
!    char msg[ ] = "Hello, Linux programmer!";
  
     puts(msg);
!    printf("Here you are, using diff.\n");

!    return 0;
  }
---  1,13 ---
  #include <stdio.h>
+ #include <stdlib.h>

  int main(void)
  {
!   char msg[] = "Hello, Linux programmer, from howdy.c!");
  
    puts(msg);
!   printf("howdy.c says, `Here you are, using diff.`\n");
!   exit(EXIT_SUCCESS);
  }
$

上下文块的格式采用以下一般形式:
  *** srcfile srcfile_timestamp
  --- dstfile dstfile_timestamp
  ****************
  *** srcfile_line_range ***
    srcfile line
  --- dstfile line_line_range
  dstfile line
  dstfile line...

. + -----向srcfile添加一行以创建dstfile
. - -----从srcfile删除一行以创建dstfile
. ! -----在srcfile改变一行以创建dstfile.srcfile中标记"!"的每一行或一段,在dstfile中相应的每一行或一段也标记"!".

每一块(hunk)都用一长串最多15个星号和下一块(hunk)分隔开来.
posted @ 2005-08-04 17:21 ivaneeo 阅读(239) | 评论 (0)编辑 收藏

统一格式是对上下文格式的修改版本,它不显示重复的上下文而且还用其他办法压缩输出内容.统一格式以下面的开头来标识要比较大文件:
  --- srcfile srcfile_timestamp
  其后是一个或多个块(hunk),格式如下:
    @@ srcfile_range dstfile_range @@
      line_from_either_file
      line_from_either_file
  以@@开头的每一行都标志一个块的开始.在块中,上下文行以空格开头,而有差别的行以"+"或"-"开头,以表示相对于srcfile在此位置上添加或删除一行.
命令diff -u hello.c howdy.c产生的输出如下:
  ---hello.c  Web Aug 9 21:02:42 2000
  +++howdy.c  Web Aug 9 21:04:30 2000
  @@ -1,12 +1,13 @@
    #include <stdio.h>
    +#include <stdlib.h>

    int main(void)
    {
   -     char msg [] = "Hello,Linux programmer!";
   +     char msg [] = "Hello,Linux programmer, from howdy.c!";
  
         puts(msg);
   -     printf("Here you are, using diff.\n");
   +     printf("howdy.c says, `Here you are, using diff.`\n");
   -     return 0;
   +     exit(EXIT_SUCCESS);
    }
对这一输出进行翻译,用语言来描述怎么把hello.c转变成howdy.c:
  .紧挨着#include <stdio.h>一行之后加入#include <stdlib.h>
  .紧挨着前半个大括号之后,删除
    char msg[] = "Hello, Linux Programmer!";
    并加入
    char msg[] = "Hello, Linux Programmer, from howdy.c!";
  .紧挨着puts(msg);之后,删除
    printf("Here you are, using diff.\n");
    并加入
    printf("howdy.c says, 'Here you are, using diff.'\n");
  .紧挨着最后一个空行之后,删除
    return 0;
    并加入
    exit(EXIT_SUCCESS);
虽然统一格式既紧凑又容易阅读,但是统一格式的差异文件却有一个缺点:目前,只有GNU diff能产生统一格式的差异文件而且只有GNU patch能理解统一格式.

要判别两个二进制文件的差异,只需把它们的名字作为参数传递给diff:
  $diff hello howdy
  Binary files hello and howdy differ
如果要显示有差别的行,则使用-a选项.但是需注意这样做会输出重定向到一个文件:
  $diff -a hello howdy > diffs
  Files hello.c and howdy.c differ
要查看两个文本文件是否不同但又不显示差异之处,可以使用diff的-q选项:
  $diff -q hello.c howdy.c
  Files hello.c and howdy.c differ

  假如你想忽略某种差别.实现这个目的的做法是使用-I regexp选项.
    $diff -u -I include hello.c howdy.c
    --- hello.c Web Aug 9 21:02:42 2000
    +++ howdy.c Web Aug 9 21:04:30 2000
    @@ -2,11 +3,11 @@

    int main(void)
    {
   -       char msg[ ] = "Hello. Linux programmer!";
   +       char msg[ ] = "Hello. Linux programmer, from howdy.c!";

           puts(msg);
    -      printf("Here you are, using diff.\n");
    +      printf("howdy.c says, `Here you are, using diff.\n'";
    -      return 0;
    +      exit(EXIT_SUCCESS);
    }
上面的例子使用了-I regexp来忽略"include"的行.

另一组有用的diff命令行选项能改变它对空白的处理方式.-b选项让diff忽略输入文件中空白数量的变化;-B让diff忽略删除或插入空行的改动;-w在逐行比较时忽略空白的变化.-b和-w的区别在哪里?-b忽略的是输入文件之间空白数量上的变化,而-w则忽略在原本没有空白的地方添加的空白.
posted @ 2005-08-04 17:20 ivaneeo 阅读(774) | 评论 (0)编辑 收藏

注:而2路hunk则在"===="后加上1,2或3来指出引起不同的那个文件.

$diff3 sigrot.2 sigrot.1 sigrot.3
产生如下的输出(在这里因为空间的原因对输出做了截断):
  ====
  1:3c
    #Version 2.0
  2:3c
    #Version 1.0
  3:3c
    #Version 3.0
  ====1
  1:9,10c
    srcdir=$HOME/doc/signatures
    srcfile=$srcdir/$sigfile
  2:8a
  3:8a
  ====1
  1:12c
    old=$(cat $srcdir/num)
  2:10c
  3:10c
    old=$(cat num)
  ...
第一个hunk是3路hunk,其他的都是2路hunk.从sigrot.1或sigrot.3中生成sigrot.2时,必须把从sigrot.2中来的下面两行添加到sigrot.1或sigrot.3的第8行后:
  srcdir=$HOME/doc/signatures
  srcfile=$srcdir/$sigfile
类似地,若要依据sigrot.2来生成sigrot.1,必须把sigrot.1的第10行改为sigrot.2中来的第12行.

可以使用-m或--merge选项来告诉diff3对文件进行合并,然后再手工对结果排序:
$diff3 -m sigrot.2 sigrot.1 sigrot.3 > sigrot.merged

程序清单6.7 使用diff3合并选项产生的输出
  #!/usr/local/bin/bash
  #sigrot.sh
  <<<<<<< sigrot.2
  #Version 2.0
  |||||||sigrot.1
  #Version 1.0
  =======
  #Version 3.0
  >>>>>>> sigrot.3
  #Rotate signatures
  #Suitable to be run via cron
  ############################

  sigfile=signature
  srcdir=$HOME/doc/signatures
  srcfile=$srcdir/$srcfile

  old=$(cat $srcdir/num)
  let new=$(expr $old+1)

  if [ -f $srcfile.$new ]; then
    cp $srcfile.$new $HOME/.$sigfile
    echo $new > $srcdir /num
  else
    cp $srcfile.1 $HOME/.$sigfile
    echo 1 > $srcdir /num
  fi

  return 0

"<<<<<<<"标记对应myfile,">>>>>>>"对应yourfile,"|||||||"对应oldfile.在本例中,只需要最新的版本号,为了成功合并3个版本,将删除标记行和1.0及2.0版本指定的行.
posted @ 2005-08-04 17:19 ivaneeo 阅读(351) | 评论 (0)编辑 收藏

当两个人同时修改一个公用文件时,diff3就会发挥作用.它比较两个人做出的两套修改内容,创建第3个文件保存并后的输出结果,并且指出双方修改的冲突之处.diff3的语法是:
diff [options] myfile oldfile yourfile
oldfile是派生出myfile和yourfile的共同源文件.
  程序清单6.4 sigrot.1
    #!/bin/bash
    #sigrot.sh
    #Version 1.0
    #Rotate signatures
    #Suitable to be run via cron
    ############################
    sigfile=signature
    
    old=$(cat num)
    let new=$(expr $old+1)

    if [ -f $sigfile.$new ]; then
      cp $sigfile.$new .$sigfile
      echo $new > num
    else
      cp $sigfile.1 .$sigfile
      echo 1 > num
    fi

  程序清单6.5 sigrot.2
    #!/bin/bash
    #sigrot.sh
    #Version 2.0
    #Rotate signatures
    #Suitable to be run via cron
    ############################

    sigfile=signature
    srcdir=$HOME/doc/signatures
    srcfile=$srcdir/$sigfile
    old=$(cat $srcdir/num)
    let new=$(expr $old+1)

    if [ -f $srcfile.$new ]; then
      cp $srcfile.$new $HOME/.$sigfile
      echo $new > $srcdir/num
    else
      cp $srcfile.1 $HOME/.$sigfile
      echo 1 > $srcdir/num
    fi

  程序清单6.6 sigrot.3
    #!/bin/bash
    #sigrot.sh
    #Version 3.0
    #Rotate signatures
    #Suitable to be run via cron
    ############################

    sigfile=signature
    
    old=$(cat num)
    let new=$(expr $old+1)

    if [ -f $sigfile.$new ]; then
      cp $sigfile.$new .$sigfile
      echo $new > num
    else
      cp $sigfile.1 .$sigfile
      echo 1 > num
    fi
    return 0;

diff3在列举hunk的同时给出了生成这些hunk所需的一个或多个命令(仍旧使用ed形式).这些命令如下:
.file:la  该hunk出现在第1行后,但在file中不存在这个hunk,所以如果要依据file生成其他文件,必须加入在第1行后这个hunk.
.file:rc  该hunk由file的中第r行组成,因此在生成其他文件时必须对该行进行指定的修改.
posted @ 2005-08-04 17:16 ivaneeo 阅读(270) | 评论 (0)编辑 收藏

                           patch选项
选项                    含义
-c                      把输入的补丁文件看作是上下文格式的差异文件
-d dir                  把dir设置为解释补丁文件名的当前目录
-e                      把输入的补丁文件看作时ed脚本
-F num| --fuzz=NUM      把非精确匹配的fuzz因子设置为NUM行
-l                      把不同的空字符序列视为相同
-n                      把输入的补丁文件看作是正规格式的差异文件
-pnum| --strip=NUM      剥离文件名中的前NUM个目录成分
-R                      假定在生成补丁的命令中交换了老文件和新文件的次序
-s                      除非方式错误,否则保持缄默
-t                      执行过程中不要求任何输入
-u                      把输入的补丁文件看作是统一格式的差异文件
-v                      显示patch的版本信息并退出

当patch程序运行时,它会对将要改动的每个源文件做备份,在备份文件名的末尾加上.orig作后缀.如果patch程序不能应用某个块(hunk),它会用补丁文件中存储的文件名加上.rej(拒绝)后缀来保存该块.
posted @ 2005-08-04 17:13 ivaneeo 阅读(168) | 评论 (0)编辑 收藏

$diff -c sigrot.1 sigrot.2 > sigrot.patch
或者使用
$diff -u sigrot.1 sigrot.2 > sigrot.patch
如果源代码树内包含子目录,则在使用diff时指定-r(recursive)选项以告诉diff在创建补丁文件时遍历所有子目录.
posted @ 2005-08-04 17:11 ivaneeo 阅读(150) | 评论 (0)编辑 收藏

使用补丁的命令行如下:
  $patch -p0 < sigrot.patch
-pnum 选项指定使用补丁前补丁中所包含的文件名中需要剥离的"/"的重数.例如,如果补丁中的文件名是/home/kwall/src/sigrot/sigrot.1,则-p1的结果是home/kwall/src/sigrot/sigrot.1;-p4的结果是/sigrot/sigrot.1;-p则剥去了除最终文件名之外的所有部分,得到sigrot.1.

  如果在安装完补丁后发现错误,只要简单地在原命令行中加上-R选项后再安装一次该补丁就能得到原来的文件:
$patch -p0 -R < sigrot.patch
posted @ 2005-08-04 17:10 ivaneeo 阅读(186) | 评论 (0)编辑 收藏

                                      版本控制术语
名称                    说明
RCS File                在RCS目录下的文件,由RCS控制,并通过RCS命令存取.一个RCS文件包含某一特殊文件的所有版本.通常,RCS文件的扩展名是.v
Working file            从RCS源代码库(即RCS目录)中检索到的一个或多个文件,放置在当前工作目录下,并能够被编辑.
Lock                    以编辑目的取回工作文件时别人就不能同时编辑这个文件.此时,文件由第一个编辑它的人锁定
Revision                源文件的一个特定版本,用数字标识.Revision的编号从1.1开始,并依次递增,除非强制指定修订版号
posted @ 2005-08-04 15:29 ivaneeo 阅读(150) | 评论 (0)编辑 收藏

仅列出标题
共67页: First 上一页 59 60 61 62 63 64 65 66 67 下一页