How to Create and Apply Patches in GIT using diff and apply Command

by Aaron Tabor on March 24, 2014

Git LogoCreating a patch in GIT is a great way to share changes that you are not yet ready to push to a public branch of a project.

To better understand how we will create a patch, lets first discuss a little about how GIT stores changes.

If you are new to GIT, install git and get a jumpstart from this GIT introduction article.

The first time a file is committed to a project in GIT, a copy is stored. For all commits after that, GIT essentially stores instructions telling it how to transform the previous version of the project to the newly committed version.

In GIT, these instructions are called “diffs” . Whenever you checkout a branch, GIT will basically start at the original state of the project, and apply all of these diffs in order, to to get to the desired state.

Knowing now how GIT stores commits, it is easy to see that a patch file will simply be a concatenation of the diffs for each of the commits that the patch will span.

For our example, lets assume the following situation: We have a simple project with 2 branches: master and experimental.

$ git log --oneline --all
  * b36f227 (experimental) third commit -- added file3
  * f39ebe8 second commit -- added file2
  * 04a26e5 (HEAD, master) first commit -- committed file1

Master is currently at the first commit, while experimental is 2 commits ahead of it. In each commit, I added a file named file1, file2, and file3 respectively. Here is the current state of each branch:

On master, we only have file1:

$ git status
On branch master
nothing to commit, working directory clean

$ ls
file1

While on experimental, we have all 3 files:

$ git status
On branch experimental
nothing to commit, working directory clean

$ ls
file1 file2 file3

In this tutorial, we’ll explain how to create a patch of the changes on the experimental branch and apply them to the master.

Creating the GIT Patch

We will use the git diff command to create the diff output, then redirect it into a file. The form of the diff command we will use is as follows:

git diff from-commit to-commit > output-file

where:

  • from-commit – the point at which we want the patch to start. (In our case, the point at which experimental diverges from master)
  • to-commit – the patch will span the changes up to and including this point. (In our case, the most recent commit of experimental)
  • output-file – the patch will be written here

Note: if either from-commit or to-commit are omitted, they will be assumed to be HEAD

We specify the two commits by their unique hash. Generally, you only have to specify enough of the commit hash to ensure its uniqueness (4 characters will probably do it).

$ git diff 04a2 b36f > patch.diff

$ ls
patch.diff file1      file2      file3

As you see from the above output, the patch file has been created.

In this special case, where we want to create a patch of the entire branch, we can let GIT do some of the work for us. We can let GIT determine the point at which our experimental branch diverged from the master branch using the git merge-base command:

git diff $(git merge-base <public branch> <experimental branch>) > <output file>

git merge-base will determine the most recent common commit between 2 branches. Notice also how this time we have omitted . It will be defaulted to HEAD, and since the experimental branch checked out, HEAD will be the most recent commit of the experimental branch.

$ git diff $(git merge-base master experimental) > anotherPatch.diff

$ ls
anotherPatch.diff patch.diff  file1  file2  file3

Again, the patch file has been created. These patch files are identical.

Applying the GIT Patch

Once the patch file has been made, applying it is easy. Make sure that the branch you have checked out is the one that you want to apply the patch to (master in our case). Then you can apply the patch using the git apply command: git apply

$ git status
On branch master
... (rest of output omitted) ...

$ ls
anotherPatch.diff patch.diff  file1

$ git apply patch.diff

$ ls
anotherPatch.diff patch.diff  file1  file2  file3

The changes from the experimental branch have now been replicated on master.

Warning: Although applying a patch in this way will exactly replicate content, no commit history will be replicated. This means that even if the patch you create spans several commits, it will appear as a single set of changes when applied. You will lose both the knowledge of how the commits were broken up and also the messages for each commit. Lets compare the commit history for both branches:

On experimental, we had 3 commits, each with a meaningful commit message.

$ git branch
  * experimental
    master
$ git log --oneline
  b36f227 third commit -- added file3
  f39ebe8 second commit -- added file2
  04a26e5 first commit -- committed file1

However, our patch simply applied the actual changes to the master branch.

$ git branch
  experimental
  * master
$ git log --oneline
  04a26e5 first commit -- committed file1

Applying the patch did not commit the changes, nor did it bring any of the commit history associated with these changes with it. Be cautious of this when using patches in GIT.


Linux Sysadmin Course Linux provides several powerful administrative tools and utilities which will help you to manage your systems effectively. If you don’t know what these tools are and how to use them, you could be spending lot of time trying to perform even the basic administrative tasks. The focus of this course is to help you understand system administration tools, which will help you to become an effective Linux system administrator.
Get the Linux Sysadmin Course Now!

If you enjoyed this article, you might also like..

  1. 50 Linux Sysadmin Tutorials
  2. 50 Most Frequently Used Linux Commands (With Examples)
  3. Top 25 Best Linux Performance Monitoring and Debugging Tools
  4. Mommy, I found it! – 15 Practical Linux Find Command Examples
  5. Linux 101 Hacks 2nd Edition eBook Linux 101 Hacks Book

Bash 101 Hacks Book Sed and Awk 101 Hacks Book Nagios Core 3 Book Vim 101 Hacks Book

{ 3 comments… read them below or add one }

1 Sebastian March 25, 2014 at 5:30 am

What about using git-format-patch ?

2 Madhab April 1, 2014 at 3:41 am

Hi,
How is apply patch different from merging the experimental branch to master? The merge action too will update the master with the same changes as that of experimental. Better yet the change history will be preserved.
Also , if possible please share under what situation you need to use patch?

Thanks

3 DarkVenger April 3, 2014 at 3:45 am

@Madhad,

applying a patch is no different from merging as you point out, however consider you want to send the changes to someone elsewhere. It is really usefull and pratical to send him/her a patch.

Leave a Comment

Previous post:

Next post: