I edit a lot of text files. Sometimes it's code. Other times it's the written word for role-playing games (RPGs), programming books, or general correspondence. Sometimes it's nice to make a change, but for my collaborator to compare my change with what they originally had written. Many people default to office suites, like LibreOffice, using comments or change tracking features. Sometimes a simpler tool makes more sense, though, and for that, you can look at programming history for tools like
patch, which provide standardized formatting for tracking and applying changes to shared files.
Even with a simple file, there's complexity in synchronizing two documents. Some items get changed, others are left alone, new content gets added, and some stay the same but are moved to different places in the document. It's difficult to replicate changes without blissfully accepting that all changes are equally valid, and replacing the old file with the new one. It's also monolithically opaque. There are so many changes that it's difficult to pick out exactly what's changed.
diff command, you can create a record of how the file has changed, and with
patch you can "replay" those changes over the old version to bring it up to date with the new version.
Suppose you and I are collaborating on a file describing how to make a cup of tea.
So far, the file
tea.md contains raw copy-paste:
Boil water. Warm the teapot. Add tea and water to the teapot. Place a tea cosy over the teapot. Steep for 6 minutes. Pour tea into cup. Add milk.
It seems reasonable, but there are always optimizations you can make, so you send the file to me for improvement. In an effort to clarify the tea-making process, I copy the file as
tea-revision.md and edit it, ending up with this:
Warm a teapot in the proving drawer of your oven. Boil water. Add tea leaves to a tea strainer. Add strainer and water to teapot. Steep for 6 minutes. Keep it warm with a tea cosy. Pour tea into cup. Optionally, add warm milk.
As expected, some items (
Boil water and
Pour tea into cup) are unchanged, while other lines (
Warm the teapot) have had additions. Some lines are completely new, and some lines are the same but in a different order.
Create a diff
diff tool displays the difference between two files. There are a few different ways to view the results, but I think the clearest one is the
-u for short) view, which shows which lines got added or subtracted. A line that's changed in any way is treated as a line that got subtracted and then added. By default,
diff prints its output to the terminal.
diff with the old file and then the new file:
$ diff --unified tea.md tea-revised.md --- tea.md 2021-11-13 10:26:25.082110219 +1300 +++ tea-revised.md 2021-11-13 10:26:32.049110664 +1300 @@ -1,7 +1,7 @@ +Warm a teapot in the proving drawer of your oven. Boil water. -Warm the teapot. -Add tea and water to the teapot. -Place a tea cosy over the teapot. -Steep for 6 minutes. +Add tea leaves to a tea strainer. +Add strainer and water to teapot. +Steep for 6 minutes. Keep it warm with a tea cosy. Pour tea into cup. -Add milk. +Optionally, add warm milk.
A plus sign (
+) at the beginning of a line indicates something that's gotten added to the old file. A minus sign (
-) at the beginning of a line indicates a line that's gotten removed or changed.
Create a patch with diff
A patch file is just the output of the
diff --unified command placed into a file. You can do this using standard Bash redirection:
$ diff -u tea.md tea-revised.md > tea.patch
The contents of the file are exactly the same as what was output to the terminal. I like to view patch files in Emacs, which color-codes each line depending on whether it's gotten added or subtracted.
Applying changes with patch
Once I have a patch file, I could send it to you for you to review and, optionally, apply to your old file. You apply a patch with the
$ patch tea.md tea.patch
Lines got added, lines got subtracted, and in the end, you end up with a file identical to my version:
$ cat tea.md Warm a teapot in the proving drawer of your oven. Boil water. Add tea leaves to a tea strainer. Add strainer and water to teapot. Steep for 6 minutes. Keep it warm with a tea cosy. Pour tea into cup. Optionally, add warm milk.
There's no limit to how many times you can patch a file. You could iterate on my changes, generate a new patch, and send that to me for review. Sending changes rather than results lets each contributor review what changed, decide what they want to keep or eliminate, and accurately document the process.
If you've ever tried to collaborate on files over email or chat, and you've found yourself trying to describe where you need a change made, then you'll love
patch. A carefully structured file, such as code or line-delimited Markdown, is easy to diff, patch, and maintain.