
Create a patch from differences in a file with the diff and patch commands
When you collaborate on a digital project with someone, it’s a guarantee that eventually someone’s going to need to send you changes they’ve made to a file.
As websites and web browsers have become more complex, some useful methods have been developed to help you track and apply changes to a file. There’s live collaborative editing, there are source code management systems like Git, and version tracking systems. But there’s an older system that’s less interactive than many of the tools you find in a web browser, but it’s also not dependent on a complex software stack. Instead, you can use the local diff
and patch
commands to generate differentials (a “diff”) and then merge (or “patch”) changes into an existing file.
Setup
First, create an example file containing every other like of the first two stanzas of William Blake’s poem Tyger:
In the forests of the knight;
Could frame thy fearful symmetry?
In what distant deeps or skies.
On what wings dare he aspire?
For a little extra variety, I’ve introduced a typo in the first line.
Instead of night
, I’ve typed knight
.
Save this file as poem.txt
in a directory called blake
.
1. Make a copy of the file, and modify it
Suppose you were collaborating on a project and noticed that William Blake’s poem had been incorrectly transcribed.
First, make a copy of the project directory. This usually happens as a natural part of sharing files collaboratively. When someone makes a file available on a shared server or sends you a file over email, they don’t delete their copy of the file. You’re working on a copy because that’s just how digital technology works. Git, for example, stores a copy of every committed file whether you think about it or not. You need the original version of the file handy in order to make a diff, however, so for this example, make a copy of the project directory as you received it so you can compare your end result with the directory as it was before you started working on it:
$ cp -r blake blake-revision
Change directory to your version of the project:
$ cd blake-revision
Add the missing lines of the poem:
Tyger Tyger, burning bright,
In the forests of the night;
What immortal hand or eye,
Could frame thy fearful symmetry?
In what distant deeps or skies.
Burnt the fire of thine eyes?
On what wings dare he aspire?
What the hand, dare seize the fire?
2. Create a diff
You can create a diff of a single file or for an entire directory. It’s usually easiest to make a diff of an entire directory.
$ diff --unified --recursive --new-file \
blake blake-revision > my.patch
One of the nice things about a patch file is that it’s human-readable. The recipient technically doesn’t even need to use patch
to apply the changes, because the changes are provided as plain text notation. You can look at it for yourself:
$ cat my.patch
diff --unified --recursive --new-file blake/poem.txt blake-revision/poem.txt
--- blake/poem.txt 2025-03-18 15:44:51.382188010 +1300
+++ blake-revision/poem.txt 2025-03-18 15:02:57.398577083 +1300
@@ -1,4 +1,9 @@
-In the forests of the knight;
+Tyger Tyger, burning bright,
+In the forests of the night;
+What immortal hand or eye,
Could frame thy fearful symmetry?
+
In what distant deeps or skies.
+Burnt the fire of thine eyes?
On what wings dare he aspire?
+What the hand, dare seize the fire?
As you can see, the patch file identifies the location of the two files compared, and then details what must be done to blake/poem.txt
to make it match the blake-revision/poem.txt
file. A minus sign (-
) at the start of a line indicates that the line must be removed. A plus sign (+
) at the start of a line indicates that a line must be added. It’s entirely linear, moving from line to line and making whatever adjustment is necessary.
3. Patch
Move the blake-revision
directory to your system trash. Assume that instead of creating my.patch
, you’ve just received it from a collaborator, along with an email noting that your copy of William Blake’s poem was incomplete (and contained a typo). Don’t worry, though, your collaborator has made the necessary corrections, contained in my.patch
.
To make your version of Blake’s poem match your collaborator’s version, you use the patch
command. There’s a catch, though. Your collaborator was working in a directory called blake-revision
, which doesn’t exist on your system. You have a directory named blake
. This produces a non-fatal error, which you can see for yourself by running patch
with no extra options. Run the command from the directory containing the blake
folder (do not change directory into blake
):
$ patch < my.patch
can't find file to patch at input line 4
Perhaps you should have used the -p or --strip option?
The text leading up to this was:
--------------------------
|diff --unified --recursive --new-file blake/poem.txt blake-revision/poem.txt
|--- blake/poem.txt 2025-03-18...
|+++ blake-revision/poem.txt 2025-03-18...
--------------------------
File to patch:
Press Ctrl+C to cancel.
The patch
command is robust and can recover from small path errors, but it’s even easier to avoid the error altogether. When the base directory of the new version of a file doesn’t exist on your system, you can make patch
ignore (or “strip”) one or more directories leading up to your target file. Confusingly, patch
starts counting at zero, so to strip the first directory from the path, you must actually strip the zeroeth directory.
$ patch --strip 0 < my.patch
patching file blake/poem.txt
Take a look at the new version of your file:
$ cat blake/poem.txt
Tyger Tyger, burning bright,
In the forests of the night;
What immortal hand or eye,
Could frame thy fearful symmetry?
In what distant deeps or skies.
Burnt the fire of thine eyes?
On what wings dare he aspire?
What the hand, dare seize the fire?
Diff and patches tips and tricks
If you’re a Git user, then creating diffs and applying patches is technically already part of your daily workflow. If you’re accustomed to working in LibreOffice or Google Doc files, then this might seem inconvenient. As someone who uses diffs and patches both inside and outside of Git, I have a few tips on how to make diffs and patches easier than tracking changes in word processor documents.
- Write in Commonmark (Markdown) or Asciidoc. These formats don’t require a word processor, just a text editor.
- It feels strange at first, but write each sentence on a new line. This way, your diff can make small corrections by replacing just a line, instead of having to replace a whole paragraph.
- Make a working copy early. I’ve definitely been guilty of opening a project directory with the intent to make no changes, but of course that never happens. There’s always a mistake somewhere.
- Use source control management, like Git or Fossil, and let it handle diffs and patches!
Daily workflow
Make a copy, make your changes, make a diff.
That’s the workflow, and it really is that simple.
There have been times when I’ve received a proposed patch for a project that’s 90% good, and 10% not something I want to incorporate. I use GNU Emacs to edit the patch file because it calculates and updates the unified patch header data for me, so I can change the patch and apply it. You can selectively accept changes with Git, but this is a direct method of cherry-picking, and sometimes the direct method is faster.
If you’re tired of the overhead of tracking changes your current collaboration solution imposes, consider giving diff
and patch
a try.