Patch

From APIDesign

Revision as of 06:24, 21 January 2026 by JaroslavTulach (Talk | contribs)
(diff) ←Older revision | Current revision (diff) | Newer revision→ (diff)
Jump to: navigation, search

How can a patch be distributed? When accepting API Patches and having proper Git repository infrastructure one can probably think of a patch as a pull request. However, there are older and I'd like to claim still useful ways to deliver patches that work well with Git and other versioning systems. In fact this old good way is still in the heart of these versioning systems. I am talking about:

diff --git channel/Channel.java channel/Channel.java
index da14c1bce6..0db8858d0a 100644
--- a/channel/Channel.java
+++ b/channel/Channel.java
@@ -493,13 +494,10 @@ public final class Channel<Data extends Channel.Config> implements AutoCloseable
    * @return {@code true} if the exception was printed and further details should be printed
    */
   private boolean printStackTrace(Throwable ex, boolean userCode) {
-    if (!userCode) {
       if (ex != null) {
         ex.printStackTrace();
       }
-      return true;
-    }
-    return false;
+    return  true;
   }
 
   /**

Contents

Quiz

What do you think about the above text?

  • I have a feeling I understand the patch
  • I known what those lines starting with + and - mean
  • I can apply the same changes to existing Channel.java file manually
  • I known tool to apply the changes for me
    • It is a UI application
    • I can do it from command line
    • I ask AI to apply the change for me
  • I know the -p argument of the CLI command
  • I know the -R argument of the CLI command
  • I know something more than you!


Answers

Reading

My colleague Ilya wrote: " In most cases, I will just observe the patch without applying it if it is small enough. (it usually is!)". In such case the situation is simple. Lines starting with a single - are the ones being removed and those starting with a single + are those being added. The header identifies the file that's being modified, but one doesn't really have to parse it - it is clear the above patch is related to Channel.java file.

Trying It

However sometimes just reading isn't enough. Sometimes we need to apply the patch locally to try how it behaves. Let's quote Ilya one more time: "If it is small enough (a few lines), I will repeat it manually, if ... typing everything by hand is not an option, I will apply it with git." I am not fully sure how to apply a patch with git, but let's do it with another program (years older than git) which is (unsuprisingly) named patch.

$ patch -p0 <my.diff

The -p argument is very important. Without it patch command doesn't know how to interpret the header and locate the Channel.java file. In such case the patch command switches to interactive mode - which is quite annoying (but it shows how old the patch command is - it comes from ages when interactions with user were happening in terminal and not a GUI). Using -p argument avoids the interactivity.

With -p0 the above patch seeks for channels/Channel.java file. One can use -p1 to instruct patch utility to strip one level from the specified directories. Then the utility would be looking for Channel.java file only. By default use -p1 for diffs generated by git diff command.

Pipe It!

The patch command expects the changes on stdio - hence the < to send my.diff file in. That can be useful to cherry pick any git commit. Just try:

$ git show 88e601f | patch -p1

and the changes from 88e601f commit will be applied just like you'd typed them manually. Simple way to extract changes from git history without git knowing anything about it - e.g. without changing the internals of the local git repository at all.

Embeddable Format

The above diff format can be easily embedded into an email and sent as a part of a message. E.g. surrounding the patch with prose sections as completely OK. The patch command line tool will just ignore everything not having the appropriate diff header

Applying a PR from Another GitHub Repository

A neat trick is to feed patch directly from GitHub. Did you know each pull request URL can be appended with .diff or .patch and then one gets a plain text page in patch format? As such one can:

$ curl -L https://github.com/enso-org/enso/pull/14666.diff | patch -p1

Get all changes in 14666 PR and pipe the output directly to patch utility. Don't forget to remove one directory from paths (as by default Git's prepends a and b to differentiate between original and target file) by applying -p1.

Conclusion

I have been adding (sometimes complicated) diffs as PR comments for many years and just recently I realized that I am not sure people know how to apply them! That's why I decided to write this down. I find the patch command line utility very useful. I wish its knowledge would spread. Let this little quiz help with that!

Personal tools
buy