Diff, Patch, and Friends

“Kernel patches” may sound like magic, but the two tools used to create and apply patches are simple and easy to use—if they weren't, some Linux developers would be too lazy to use them...
Chunks

Near the beginning of this article, I promised to explain this line:

 -1,9 +1,9

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.

Other formats

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.

______________________

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

The first comment asked for

Anonymous's picture

The first comment asked for reasons. Here are a few.

1. Years of fighting with graphical tools can lead one to learn command line tools.

2. A major difference between the two is the former can be used in scripts.

3. Another significant difference is robustness. It's generally much easier to crash a graphical tool than a well-designed command line one.

4. Lastly, command line tools most often contain less code and require less system resources to operate, often making them better suited to work faster and more efficiently than graphical tools.

Smaller, faster and more reliable. Built for automation. A higher learning curve may be a trade off for higher performance.

Why?

Jonathan Allen's picture

Why in the world would I want to fight with command line tools when trying to compare and merge versions? Graphical diff and merge tools have existed for decades.

Now if you can show me a diff and merge tool that understands the syntax of the file being compared and I'll be far more interested. I have seen merge tools eat a brace way too often.

I think the images for figure

Anonymous's picture

I think the images for figures 1 and 2 are broken. When I follow the links to view these figures, the images don't show up in my browser window.

using diff and patch

John's picture

If I use diff -Naur to generate a patch symbolic links are not respected. e.g. see below;

How can I get patch/diff to respect symbolic links?

>---------------------------------------------------<
$ ll foo*
foo:
total 4
lrwxrwxrwx 1 foo users 5 Jun 9 13:04 link -> stuff
-rw-r--r-- 1 foo users 12 Jun 9 13:04 stuff

foo2:
total 4
lrwxrwxrwx 1 foo users 5 Jun 9 13:04 link -> stuff
-rw-r--r-- 1 foo users 12 Jun 9 13:04 stuff

$ diff -Naur foo foo2 > patch
$ mv foo2 foo2.orig
$ patch -p0 < patch
patching file foo/link
patching file foo/stuff

$ ll foo
total 8
-rw-r--r-- 1 foo users 27 Jun 9 13:08 link
-rw-r--r-- 1 foo users 27 Jun 9 13:08 stuff

>---------------------------------------------------<

Working with directories

Anonymous's picture

This article is missing info on patching multiple files.

See here: http://lists.gnu.org/archive/html/help-gnu-utils/2004-06/msg00024.html for examlpe.

Re: Diff, Patch, and Friends

Anonymous's picture

Nice article! I now link to it from
my "Howto contribute to an open source project" tutorial,
www.kegel.com/academy/opensource.html

Re: Diff, Patch, and Friends

Anonymous's picture

You may want to link to the manpages for the free versions
of diff and patch too, instead of only the GNU versions:

http://mirbsd.bsdadvocacy.org/man1/diff.htm
http://mirbsd.bsdadvocacy.org/man1/patch.htm

To the editor: ed(1) is by no means obsolete; I'm actually
faster with ed than with vi (whose modus operandi is
cruelly to a wordstar-compatible editor user like me).

http://mirbsd.bsdadvocacy.org/man1/ed.htm

You didn't mention diff3 either, did you?

Webinar
One Click, Universal Protection: Implementing Centralized Security Policies on Linux Systems

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Learn More

Sponsored by Bit9

Webinar
Linux Backup and Recovery Webinar

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.

Learn More

Sponsored by Storix