Git Patching

Hello fellow coders, today’s topic is on Git and the use of patch files.  If you who are unfamiliar with Git, especially if you’re not a developer, you may want to read up about that Git Logofirst and then come back here to fully understand what I’m talking about.  You can find out what Git is by going here.  If you want to read an entire book on Git I suggest you click here.

What this blog entry is not, is about fixing up that bloody rotten git you know.  Git in this case does not refer to that person that you consider to be foolish or worthless; as described by the Merriam Webster dictionary.  No, rather Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.  At the time of this writing the latest version of Git is 1.8.1.2.

A Git patch is file that contains the changes that you have made to something that has been source controlled.  For the purposes of this article, I’m going to create a simple hello world console application.  Exciting isn’t it?  Here is the basic code:

using System;

namespace HelloWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World");

            Console.ReadLine();
        }
    }
}

Super simple right? I’ve created the initial project and committed my changes to the “master” branch. For the sake of this article, I’m going to say that the code that we ship to the customer is shipped from the “master” branch. Now I’m going to create a new branch using the following command in the Git Bash console.

$ git checkout -b develop

Git very nicely creates a new branch for me called “develop” and moves me into that branch.
Development moves on in the application and we end up with code that looks like this in the development branch.

using System;

namespace HelloWorld
{
    class Program
    {
        private const string MESSAGE = "Hello {0}";

        static void Main(string[] args)
        {
            Console.WriteLine(String.Format(MESSAGE, args[0]));

            Console.ReadLine();
        }
    }
}

Now the customer gets the program and determines that requiring the user to press the enter key at the end of the program is causing a problem. They also would like some punctuation at the end of the message that is displayed. As developers we should be so lucky that these are our problems, but bear with me here.
We could create a defect branch that derives from develop and fix it there, but then how do we get the fix to the customer? If we merge the changes from develop into the master branch we will introduce code that we don’t want the customer to have yet. Our other option is to fix the problems in both branches. For the changes that I’m describing here that may not be that big a deal. But when you start modifying a lot of files over a couple projects this work could be quite daunting.
What is the solution?
You create a patch file.
As with any source control solution, the entire file is not preserved when you make changes to code. Only the changes are stored. A playback of these changes in the right order determine what your final code file will look like. We can create a “patch file” that only contains the changes that you have made.
I’m going to create a patch file for the changes that we made in our defect branch using the following command in the Git Bash console.

$ git diff HEAD^ --no-prefix --ignore-space-at-eol > defect101.diff

What this will do is look at the project differences from one commit back or HEAD minus one. I could have also put the appropriate SHA value in place of head if I wanted to roll back even further in time. You can even generate a diff that compares what has happened between two different commits as shown below:

$ git diff 81b09bd 72cf13c --no-prefix --ignore-space-at-eol > defect101.diff

In this manner you can create a single patch file that contains many different commits It will then output all of these changes to a console which I have redirected the output of into the file “defect101.diff”.

NOTE: You should create your diff files outside of your source controlled folders so that when you switch branches, your diff files does not go away.

Let’s take a look at the content of that diff file.

diff --git src/HelloWorld/Program.cs src/HelloWorld/Program.cs
index a2ac871..1af6e5e 100644

--- src/HelloWorld/Program.cs
+++ src/HelloWorld/Program.cs
@@ -6,9 +6,7 @@ namespace HelloWorld
     {
         static void Main(string[] args)
         {
-            Console.WriteLine("Hello World");
-
-            Console.ReadLine();
+            Console.WriteLine("Hello World!");
         }
     }
 }

Now this patch file tells us exactly what is going on, we are deleting the read line method and the extra space form the code file. The existing WriteLine method is being removed and re-added with the punctuation that the customer wanted.

Warning: Patching is something that should never be done on your production site unless you have sufficient backup and testing performed. While patching itself is relatively easy, understanding the implications of a patch is not. Patching your system can lead to loss of data and/or site instabilities.

Now we are ready to apply the changes to both branches. First switch to the master branch so that the customer can receive the requested changes. Then issue the following patch command.

$ patch -p0 < defect101.diff

This will make the changes to the file and when you do a “git status” you will see the following output.

$ git status
# On branch master
# Changes not staged for commit:
#   (use "git add ..." to update what will be committed)
#   (use "git checkout -- ..." to discard changes in working directory)
#
#       modified:   src/HelloWorld/Program.cs
#
no changes added to commit (use "git add" and/or "git commit -a")

I will commit the changes to the repository with the following lines:

$ git add -A
$ git commit -m 'DEFECT101 - Removing the read line and adding an exclamation point.'

Now all I need to do to get this fix into the development branch “develop” is change to that branch and repeat the procedures above.
I’ve gotten in the habit of creating a patch file whenever I’m ready to merge a series of commits into another branch, because you never know when your boss will come back to you and say “Can you apply that fix in version 2.x as well?”
Hopefully now you have a better understanding of what patch files are and how to use them.
Like the blog? Drop me a line.

Until then, Happy Coding!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s