Nithin Bekal About

Creating and applying git patch files

12 Feb 2017

I was recently reviewing code on a project where I didn’t have write access, and wanted to suggest a small code change to the team. As I couldn’t send a pull request to make the change, I had to look into how to create a patch that I could then email.

Creating a patch

In this example, we will add a line to a Rails project’s Gemfile. When we add a gem 'rspec-rails' line, git diff looks like this:

diff --git a/Gemfile b/Gemfile
index c661619..989efe8 100644
--- a/Gemfile
+++ b/Gemfile
@@ -24,6 +24,7 @@ group :development do
   gem 'listen', '~> 3.0.5'
   gem 'spring'
   gem 'spring-watcher-listen', '~> 2.0.0'
+  gem 'rspec-rails'
 end

 gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

We can save this as a patch file, without committing the code.

git diff > add-rspec.patch

Now let’s look at what happens when you add a new file to the working directory. Create a notes.txt, add a couple of lines there, and run git diff. You will notice that the new file is not present in the diff. To get it, you will need to stage all the files and then run git diff --cached.

git add .
git diff --cached > add-rspec.patch

Now the patch looks like:

diff --git a/Gemfile b/Gemfile
index c661619..989efe8 100644
--- a/Gemfile
+++ b/Gemfile
@@ -24,6 +24,7 @@ group :development do
   gem 'listen', '~> 3.0.5'
   gem 'spring'
   gem 'spring-watcher-listen', '~> 2.0.0'
+  gem 'rspec-rails'
 end

 gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
diff --git a/notes.txt b/notes.txt
new file mode 100644
index 0000000..3a5e395
--- /dev/null
+++ b/notes.txt
@@ -0,0 +1,2 @@
+We are using rspec for testing.
+Rspec is the best.

Binary patches

What if the new file we added was a binary file? This time we will add a logo.jpeg file and stage it. We can use the --binary option.

git add .
git diff --staged --binary > mypatch.patch

The patch file will look like this:

diff --git a/Gemfile b/Gemfile
index c661619..989efe8 100644
--- a/Gemfile
+++ b/Gemfile
@@ -24,6 +24,7 @@ group :development do
   gem 'listen', '~> 3.0.5'
   gem 'spring'
   gem 'spring-watcher-listen', '~> 2.0.0'
+  gem 'rspec-rails'
 end
 
 gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
diff --git a/app/assets/images/logo.jpeg b/app/assets/images/logo.jpeg
new file mode 100644
index 0000000000000000000000000000000000000000..064fa38be3ecd426a3c8977ed43df627c6f6f229
GIT binary patch
literal 50966
zcmbT6RZtv2x1a}i2o6CLAUMHc&=7(LcbCE49fAa#;4l!}9R?j7La@Qz-3jh4+5Goz
z?N;s6?w*#Hmg=v%T8{i(_`3mkBQGr{4M0Eu01*Bqz~5JZu%w!lgod)35UrItyREZ@
...a few hundred lines like this...
z_i{8b#lS>d00-gE<y-oK1ih6&zzl1$iJXXs289`1p0s}urC+&SB#PYPr9*_xMg=~A
v97b_p1peNmKNs|WZ3Z9xD7de_7qxsD`+5QY01Jai0{XNQKl(o6fIt7)0U9~_

literal 0
HcmV?d00001

Creating patches from commits

Suppose you have created a new branch and made two commits - one for adding rspec to Gemfile, and another for the notes file. You can create a patch file for the commits by using git format-patch.

$ git format-patch master
0001-Add-rspec-to-gemfile.patch
0002-Add-notes-file.patch

This will create a patch file for each commit. Let’s take a look at what one of the files looks like:

From 57c9101b014623049a6bb75ee43505058d494077 Mon Sep 17 00:00:00 2001
From: Nithin Bekal <nithin@example.com>
Date: Sun, 12 Feb 2017 13:31:03 +0530
Subject: [PATCH 1/2] Add rspec to gemfile

---
 Gemfile | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Gemfile b/Gemfile
index c661619..989efe8 100644
--- a/Gemfile
+++ b/Gemfile
@@ -24,6 +24,7 @@ group :development do
   gem 'listen', '~> 3.0.5'
   gem 'spring'
   gem 'spring-watcher-listen', '~> 2.0.0'
+  gem 'rspec-rails'
 end

 gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
--
2.11.1

If you don’t want to create multiple patch files, you can do this:

git format-patch master --stdout > rspec-changes.patch

Applying a patch

Now that we have looked at the different ways to create patches, let’s see how we can apply a patch file to the working directory. Let’s checkout a review-rspec-patch branch from master first. Now let’s apply one of the patch files we created earlier:

git apply 0001-Add-rspec-to-gemfile.patch

Using git apply provides the patch as unstaged changes in your branch. If you want to apply the patches as commits, you can use git am.

$ git am rspec-changes.patch
Applying: Add rspec to gemfile
Applying: Add notes file

$ git log --oneline
ac9caff Add notes file
f784b22 Add rspec to gemfile
8619310 ...older commits...
Hi, I’m Nithin! This is my blog about programming. Ruby is my programming language of choice and the topic of most of my articles here, but I occasionally also write about Elixir, and sometimes about the books I read. You can use the atom feed if you wish to subscribe to this blog or follow me on Mastodon.