The diff examples in Section 11.1 and Section 11.2 show compact formats with just the differences between the two files. But, in many cases, context diff listings are more useful. Context diffs show the changed lines and the lines around them. (This can be a headache if you're trying to read the listing on a terminal and there are many changed lines fairly close to one another: the context will make a huge "before" section, with the "after" section several screenfuls ahead. In that case, the more compact diff formats can be useful.) A related format, unified diff, shows context but doesn't take as much space.
Go to http://examples.oreilly.com/upt3 for more information on: rcs
The rcsdiff command shows differences between revisions in an RCS (Section 39.5) file (and will only be available if you have RCS installed). We'll use it here instead of diff — but the concepts are the same. Incidentally, these examples would also work with cvs diff ( Section 39.7), if you have CVS installed.
The -c
option shows before-and-after versions of each changed
section of a file. By itself, -c
shows three lines above and
below each change. Here's an example of a C file before and after some edits;
the -c2
option shows two lines of context.
The -u
option shows changed lines next to each other, not in
separate before-and-after sections. Again, an option like -u2
shows two lines of context around a change
instead of the default three lines.
A diff -c
listing starts with the two
filenames and their last-modified dates ("timestamps"). The first
filename (here, atcat.c revision 1.1) has three
asterisks (***
) before it; the
second name (atcat.c revision 1.2) has three
dashes (---
). These markers
identify the two files in the difference listings below:
*** atcat.c 1987/09/19 12:00:44 1.1 --- atcat.c 1987/09/19 12:08:41 1.2
A diff -u
listing also starts with the two
filenames and their last-modified dates ("timestamps"). The first
filename (here, atcat.c revision 1.1) has three
minus signs (---
) before it,
meaning "from" or "before." The second name
(atcat.c revision 1.2) has three plus signs
(+++
). Again, these markers
identify the two files in the difference listings that
follow:
--- atcat.c 1987/09/19 12:00:44 1.1 +++ atcat.c 1987/09/19 12:08:41 1.2
Each difference section in a diff -c listing starts with a row of asterisks:
***************
In a diff -u
listing, each difference section
starts with a line that has a pair of line numbers and line counts.
This one means that the first version of the file (with a -
before it) starts at line 14 and
contains 5 lines; the second version of the file (with a +
) also starts at line 14 and has 5
lines:
@@ -14,5 +14,5 @@
In a diff -c
listing, changed lines that exist
in both files are marked with an !
(exclamation point) character in the left margin.
So, one of the lines between lines 15-19 was changed. Other lines in
the section weren't changed:
*** 15, 19 **** #ifndef lint static char rcsid[ ] = ! "$Id: ch11.xml,v 1.33 2002/10/13 03:51:58 troutman Exp troutman $"; #endif not lint --- 15,19 ---- #ifndef lint static char rcsid[ ] = ! "$Id: ch11.xml,v 1.33 2002/10/13 03:51:58 troutman Exp troutman $"; #endif not lint /* end of Identification */
A diff -u
listing always shows lines that
are marked with a minus (-
) only
in the first version and lines marked with a plus (+)
in the second version. Here, one
line was changed:
@@ -15,5 +15,5 @@ #ifndef lint static char rcsid[ ] = - "$Id: ch11.xml,v 1.33 2002/10/13 03:51:58 troutman Exp troutman $"; static char rcsid[ ] = + "$Id: ch11.xml,v 1.33 2002/10/13 03:51:58 troutman Exp troutman $"; #endif not lint /* end of Identification */
In a diff -c
listing, a line that exists in the
first version but not the second version is marked with a minus sign
(-
). None of the lines from
the second version are shown. So, line 62 in the first version
(lines 64-68) was deleted, leaving lines 64-67 in the second
version:
*** 64,68 **** { int i; /* for loop index */ - int userid; /* uid of owner of file */ int isuname; /* is a command line argv a user name? */ int numjobs; /* # of jobs in spooling area */ --- 64,67 ----
A diff -u
listing simply shows the deleted line
with a minus (-
) sign before it.
The section started at line 64 and had 5 lines; after the change, it
starts at line 64 and has 4 lines:
@@ -64,5 +64,4 @@ { int i; /* for loop index */ - int userid; /* uid of owner of file */ int isuname; /* is a command line argv a user name? */ int numjobs; /* # of jobs in spooling area */
In a diff -c listing, lines that are added are marked with an exclamation point (!) and only appear in the second version. So, one of the lines between lines 111-116 was changed, and two other lines were added, leaving lines 111-118 in the second version:
*** 111,116 **** * are given, print usage info and exit. */ ! if (allflag && argc) usage( ); /* --- 111,118 ---- * are given, print usage info and exit. */ ! if (allflag && argc) { usage( ); + exit(1); + } /*
In a diff -u
listing, lines that are only in
the second version are always marked with a +
. Here, one line was changed, and two lines were
added. The original version started at line 111 and had 6 lines; the
changed version started at line 111 and has 8 lines:
@@ -111,6 +111,8 @@ * are given, print usage info and exit. */ - if (allflag && argc) + if (allflag && argc) { usage( ); + exit(1); + } /*
Context diffs
aren't just nice for reading. The patch (Section 20.9) program reads context
diff listings and uses them to update
files automatically. For example, if I had the first version of
atcat.c, someone could send me either of the previous
diff listings (called a "patch"). From
the original and the patch, patch could
create the second version of atcat.c. The advantage of a
context diff over the formats in Section 11.1 and Section 11.2 is that context diffs let patch
locate the changed sections even if they've been moved somewhat. In this case,
it's probably not a good idea to save space by reducing the
number of context lines (with -c2
or -u2
, as I did here); giving all three lines of
context can help patch locate the changed
sections.