How to read a patch or diff and understand its structure to apply it manually

by Markus Bertheau, last updated on May 17th, 2013 Leave a reply »

Hi :)

I wrote this article to show you how patch/diff files store difference information. After reading it you will be able to understand patch files when you read them, better understand certain patch error messages and apply changes manually.

Patch or diff files are just text files, so you can look at them with less or a text editor.

If you prefer to use a terminal, colordiff (in the colordiff package) provides syntax highlighting. If the patch is long, you may want to use less to look at it. You need the -R option for less, or else the colors won’t show. I also always use -S, which will enable horizontal scrolling in less instead of wrapping long lines. The whole command to view a patch with syntax highlighting through less in a terminal is:

markus@ubuntu:~$ cat file.patch | colordiff | less -RS
Patch formats


Each patch file comes in , called normal, context and unified diff. You can identify them by looking at the contents of the patch file.

Normal diffs have a lot of lines that start with > or <:

...
51
< background-color: red;
---
> background-color: blue;
...

Skip to how to read a normal diff

Context diffs have a lot of lines with stars ***** in them and lines starting with !, + and -:

...
***************
*** 44,54 ****

  html, body { color: #242626; }
  html {
!   background-color: red;
    height: 100%;
    margin-bottom:;
    overflow-y: scroll;
--- 44,54 ----

  html, body { color: #242626; }
  html {
!   background-color: blue;
    height: 100%;
    margin-bottom:;
    overflow-y: scroll;
...

Skip to how to read a context diff

And finally unified diffs have a lot of lines with two @@s in them and lines starting with + and -:

...
@@ -44,11 +44,11 @@

 html, body { color: #242626; }
 html {
-  background-color: red;
+  background-color: blue;
   height: 100%;
   margin-bottom:;
   overflow-y: scroll;
...

Skip to how to read a unified diff

How to read a normal diff

The patch file contains a section for each file that should be changed. That section starts with a line identifying the file. That line has the file name and path of first the old and then the new version in it:

diff violet-park-2.orig/style.css violet-park-2/style.css

Then follow sets of changes, called hunks. The first line of each hunk contains

  • the line or line range from,to in the file before the changes
  • a letter indicating a change (c), an addition (a) or a deletion (d)
  • the line or line range in the file after the changes

all without spaces inbetween.

A change looks like this:

73
<   red
---
>   blue

That means, change line 73, which contains red, to blue. The new line is lineafter all changes.

The new line number could also have been, say, 75. In that case all additions, deletions and changes before that line added up to the file after all changes.

Instead of single line numbers, a line range can be specified, for example:

90,94
...

That means, change linesfile to the following, which will be linesfile. The same applies for additions and deletions.

An addition looks like this:

80,81
> line1
> line2

That means, in the original file after line. These will be lines.

And finally, a deletion looks like this:

77
< line1

That means, delete linefile. The line, that preceded linefile will be linefile.

How to read a context diff

The patch file contains a section for each file that should be changed. That section starts with the file name and path of first the old and then the new version and some additional information:

diff -c violet-park-2.orig/archive.php violet-park-2/archive.php
*** violet-park-2.orig/archive.php      2009-10-10 07:37:43.000000000 +0200
--- violet-park-2/archive.php   2009-10-10 09:05:58.000000000 +0200

patch is pretty lax about the format of these lines, as long as it can find out the file names. In patches generated by version control systems like cvs, svn or git these little different.

Then follow sets of changes, called hunks. Each hunk starts with a line with. Then comes a line with the line range from,to and the lines from file before the changes. Lines that start with an ! are changed, lines that start with a - are deleted. Then comes the line range and the lines in the file after all changes. Lines that start with a ! are, again, changed, and lines that start with a + are added. Each line modified by the patch is surrounded withbefore and after.

A change looks like this:

***************
*** 70,76 ****
  foo
  bar
  baz
! red
  more context
  and more
  still context
--- 70,76 ----
  foo
  bar
  baz
! blue
  more context
  and more
  still context

That means, change line 73 (= 70 + in the file before all changes, which contains red to blue. The changed line is also line 73 (= 70 + in the file after all changes.

Here’s an example for an addition:

***************
*** 75,80 ****
--- 77,84 ----
  foo
  bar
  baz
+ line1
+ linemore
  and still context

That means, in the original file after line 78 (= 75 + add . These will be lines 80 (= 77 + through.

And that’s how a deletion looks like:

***************
*** 75,81 ****
  foo
  bar
  baz
- linemore
  and still context
--- 75,80 ----

That means, delete line 78 (= 75 + in the original file. The unchanged context will be on lines.

How to read a unified diff

The patch file contains a section for each file that should be changed. That section starts with the file name and path of first the old and then the new version and some additional information:

diff -u violet-park-2.orig/archive.php violet-park-2/archive.php
--- violet-park-2.orig/archive.php      2009-10-10 07:37:43.000000000 +0200
+++ violet-park-2/archive.php   2009-10-10 09:05:58.000000000 +0200

patch is pretty lax about the format of these lines, as long as it can find out the file names. In patches generated by version control systems like cvs, svn or git these little different.

Then follow sets of changes, called hunks. Each hunk starts with a line that contains, enclosed in @@, the line or line range from,no-of-lines in the file before (with a -) and after (with a +) the changes. After that come the lines from the file. Lines starting with a - are deleted, lines starting with a + are added. Each line modified by the patch is surrounded withbefore and after.

An addition looks like this:

@@ -75,6 +77,8 @@
 foo
 bar
 baz
+line1
+linemore
 and still context

That means, in the original file after line 78 (= 75 + add . These will be lines 80 (= 77 + through.

A deletion looks like this:

@@ -75,7 +75,6 @@
 foo
 bar
 baz
-linemore
 and still context

That means, delete line 78 (= 75 + in the original file. The unchanged context will be on lines.

Finally, a change looks like this:

@@ -70,7 +70,7 @@
 foo
 bar
 baz
-red
+blue
 more context
 and more
 still context

That means, change line 73 (= 70 + in the file before all changes, which contains red to blue. The changed line is also line 73 (= 70 + in the file after all changes.

Share

Optional payment

If you found this article useful, maybe it saves you time or money, and you would like to pay for it, have a look at the paying page.

Advertisement

5 comments

  1. Barbara says:

    Thank you – this article was very helpful and I can now patch files without having to learn all about doing it with Git.

  2. Sonnyyy says:

    Thank you.

  3. Orest says:

    Than you man! Now I can try to apply a several patches to my wireless drivers and make it finally work well.

    Thanks again.

  4. Nodir says:

    Thank you very much! Very helpful.

  5. zaheer says:

    thanks Man.. that was of great helpful to me.. saved my time… Thanks for the post.

© 2016 Markus Bertheau. All rights reserved.