Diff, Patch, and Friends
Near the beginning of this article, I promised to explain this line:
that describes the chunk that diff found differences in. In each file, the chunk starts on line 1 and extends for 9 lines beyond the first line. However, with this small example, the chunk shown in the example contains the whole file. With larger files, only the lines around the changes, called the context, are shown.
In files 9 and 10, I've inserted a lot of blank lines in the middle of the paragraph, in order to show what multiple chunks look like. File 9 is damaged, file 10 is correct (except for the blank lines in the middle of the paragraph):
<h3>diff -u 9 10</h3> --- 9 Mon Apr 22 15:46:37 1996 +++ 10 Mon Apr 22 15:46:14 1996 -1,7 +1,7 Ecce Eduardus Ursus scalis nunc tump-tump-tump occipite gradus pulsante post Christophorum Robinum descendens. Est quod sciat unus et solus -modus gradibus desendendi, non nunquam autem +modus gradibus descendendi, nonnunquam autem -33,7 +33,7 sentit, etiam alterum modum exstare, dummodo -pulsationibus desinere et de no modo meditari +pulsationibus desinere et de eo modo meditari possit. Deinde censet alios modos non esse. En, nunc ipse in imo est, vobis ostentari paratus. Winnie ille Pu.
So you see that we have one seven-line chunk starting at line 1 and one seven-line chunk starting at line 33 are shown here.
You should notice several things here:
There is one header at the top of each chunk.
Blank lines are included as part of a chunk's context.
Lines that are not changed and that are not within three lines of a changed line are not included in any chunk.
“Patches” (or “diffs”) are the output of the diff program. They include all the chunks of changes between the two files.
This only brushes the surface of diff. For one thing, the three lines of unchanged context is configurable. Instead of using the -u option, you can use the -U lines option to specify any reasonable number of lines of context. You can even specify -U 0 if you don't want to use any context at all, though that is rarely useful.
What does the -u (or -U lines) argument mean? It specifies the unified diff format, which is the particular format covered here. Other formats include:
“context diffs” which have the same information as unified diffs, but are less compact and less readable
“ed script diffs” or “normal diffs” which are in a format that can be easily converted into a form that can be used to cause the (nearly obsolete) editor ed to automatically change another copy of the old file to match the new file. This format has no context and could easily be replaced by -U 0, except for compatibility with older software and the POSIX standard.
You will almost never want to create context or normal diffs, but it may be useful to recognize them from time to time. Context diffs are marked by the use of the character ! to mark changes, and normal diffs are marked by the use of the characters < and > to mark changes.
Here are examples:
diff -c 1 2 *** 1 Sat Apr 20 22:11:53 1996 --- 2 Sat Apr 20 22:12:01 1996 *************** *** 1,9 **** Ecce Eduardus Ursus scalis nunc tump-tump-tump occipite gradus pulsante post Christophorum Robinum descendens. Est quod sciat unus et solus ! modus gradibus desendendi, non nunquam autem sentit, etiam alterum modum exstare, dummodo ! pulsationibus desinere et de no modo meditari possit. Deinde censet alios modos non esse. En, nunc ipse in imo est, vobis ostentari paratus. Winnie ille Pu. --- 1,9 ---- Ecce Eduardus Ursus scalis nunc tump-tump-tump occipite gradus pulsante post Christophorum Robinum descendens. Est quod sciat unus et solus ! modus gradibus descendendi, nonnunquam autem sentit, etiam alterum modum exstare, dummodo ! pulsationibus desinere et de eo modo meditari possit. Deinde censet alios modos non esse. En, nunc ipse in imo est, vobis ostentari paratus. Winnie ille Pu. diff 1 2 4c4 < modus gradibus desendendi, non nunquam autem --- > modus gradibus descendendi, nonnunquam autem 6c6 < pulsationibus desinere et de no modo meditari --- < pulsationibus desinere et de eo modo meditari
There are a few other important things to note here:
In context diffs, the * character is used in place of the unified diff's - character, and the - character is used in place of the + character. The context diff format was designed before the unified diff format, but the unified diff format's choice of characters is mnemonic and therefore preferable.
Context diffs repeat all context twice for each chunk. This is a waste of space in files, but far more importantly, it separates the changes too widely, making patches less human-readable.
Normal, old-style diffs are very contracted and use very little space. They are useful in situations where you don't normally expect a human to read them, where saving space makes a lot of sense, and where they will never be applied to files which have changed. For example, RCS (covered in the May 1996 issue of LJ) uses a format almost identical to old-style diffs to store changes between versions of files. This saves space and time in a situation where any context at all would be a waste of space.
Free DevOps eBooks, Videos, and more!
Regardless of where you are in your DevOps process, Linux Journal can help!
We offer here the DEFINITIVE DevOps for Dummies, a mobile Application Development Primer, and advice & help from the expert sources like:
- Linux Journal
- Integrating Trac, Jenkins and Cobbler—Customizing Linux Operating Systems for Organizational Needs
- Returning Values from Bash Functions
- Tech Tip: Really Simple HTTP Server with Python
- New Products
- Non-Linux FOSS: Remember Burning ISOs?
- EdgeRouter Lite
- RSS Feeds
- Cooking with Linux - Serious Cool, Sysadmin Style!