Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

patch-package

ds3007.7mMIT8.0.0

Fix broken node modules with no fuss

readme

patch-package

patch-package lets app authors instantly make and keep fixes to npm dependencies. It's a vital band-aid for those of us living on the bleeding edge.

# fix a bug in one of your dependencies
vim node_modules/some-package/brokenFile.js

# run patch-package to create a .patch file
npx patch-package some-package

# commit the patch file to share the fix with your team
git add patches/some-package+3.14.15.patch
git commit -m "fix brokenFile.js in some-package"

Patches created by patch-package are automatically and gracefully applied when you use npm(>=5) or yarn.

No more waiting around for pull requests to be merged and published. No more forking repos just to fix that one tiny thing preventing your app from working.

Set-up

In package.json

 "scripts": {
+  "postinstall": "patch-package"
 }

Then

npm

npm i patch-package

You can use --save-dev if you don't need to run npm in production, e.g. if you're making a web frontend.

yarn v1

yarn add patch-package postinstall-postinstall

You can use --dev if you don't need to run yarn in production, e.g. if you're making a web frontend.

To understand why yarn needs the postinstall-postinstall package see: Why use postinstall-postinstall

yarn workspaces

Same as for yarn ☝️ Note that if you want to patch un-hoisted packages you'll need to repeat the setup process for the child package. Also make sure you're in the child package directory when you run patch-package to generate the patch files.

yarn v2+

yarn 2+ have native support for patching dependencies via yarn patch. You do not need to use patch-package on these projects.

pnpm

pnpm has native support for patching dependencies via pnpm patch. You do not need to use patch-package on these projects.

Heroku

For patch-package to work on Heroku applications, you must specify NPM_CONFIG_PRODUCTION=false or YARN_PRODUCTION=false. See this issue for more details.

Docker and CI

  • If having errors about working directory ("cannot run in wd [...]") when building in Docker, you might need to adjust configuration in .npmrc. See #185.
  • In your Dockerfile, remember to copy over the patch files before running [npm|yarn] install
  • If you cache node_modules rather than running yarn install every time, make sure that the patches dir is included in your cache key somehow. Otherwise if you update a patch then the change may not be reflected on subsequent CI runs.

CircleCI

Create a hash of your patches before loading/saving your cache. If using a Linux machine, run md5sum patches/* > patches.hash. If running on a macOS machine, use md5 patches/* > patches.hash

- run:
    name: patch-package hash
    command: md5sum patches/* > patches.hash

Then, update your hash key to include a checksum of that file:

- restore_cache:
    key:
      app-node_modules-v1-{{ checksum "yarn.lock" }}-{{ checksum "patches.hash"
      }}

As well as the save_cache

- save_cache:
    key:
      app-node_modules-v1-{{ checksum "yarn.lock" }}-{{ checksum "patches.hash"
      }}
    paths:
      - ./node_modules

Usage

Making patches

First make changes to the files of a particular package in your node_modules folder, then run

yarn patch-package package-name

or use npx (included with npm > 5.2)

npx patch-package package-name

where package-name matches the name of the package you made changes to.

If this is the first time you've used patch-package, it will create a folder called patches in the root dir of your app. Inside will be a file called package-name+0.44.0.patch or something, which is a diff between normal old package-name and your fixed version. Commit this to share the fix with your team.

Options

  • --create-issue

    For packages whose source is hosted on GitHub this option opens a web browser with a draft issue based on your diff.

  • --use-yarn

    By default, patch-package checks whether you use npm or yarn based on which lockfile you have. If you have both, it uses npm by default. Set this option to override that default and always use yarn.

  • --exclude <regexp>

    Ignore paths matching the regexp when creating patch files. Paths are relative to the root dir of the package to be patched.

    Default value: package\\.json$

  • --include <regexp>

    Only consider paths matching the regexp when creating patch files. Paths are relative to the root dir of the package to be patched.

    Default value: .*

  • --case-sensitive-path-filtering

    Make regexps used in --include or --exclude filters case-sensitive.

  • --patch-dir

    Specify the name for the directory in which to put the patch files.

Nested packages

If you are trying to patch a package at, e.g. node_modules/package/node_modules/another-package you can just put a / between the package names:

npx patch-package package/another-package

It works with scoped packages too

npx patch-package @my/package/@my/other-package

Updating patches

Use exactly the same process as for making patches in the first place, i.e. make more changes, run patch-package, commit the changes to the patch file.

Applying patches

Run patch-package without arguments to apply all patches in your project.

Options

  • --error-on-fail

    Forces patch-package to exit with code 1 after failing.

    When running locally patch-package always exits with 0 by default. This happens even after failing to apply patches because otherwise yarn.lock and package.json might get out of sync with node_modules, which can be very confusing.

    --error-on-fail is switched on by default on CI.

    See https://github.com/ds300/patch-package/issues/86 for background.

  • --reverse

    Un-applies all patches.

    Note that this will fail if the patched files have changed since being patched. In that case, you'll probably need to re-install node_modules.

    This option was added to help people using CircleCI avoid an issue around caching and patch file updates but might be useful in other contexts too.

  • --patch-dir

    Specify the name for the directory in which the patch files are located

Notes

To apply patches individually, you may use git:

git apply --ignore-whitespace patches/package-name+0.44.2.patch

or patch in unixy environments:

patch -p1 -i patches/package-name+0.44.2.patch

Dev-only patches

If you deploy your package to production (e.g. your package is a server) then any patched devDependencies will not be present when patch-package runs in production. It will happily ignore those patch files if the package to be patched is listed directly in the devDependencies of your package.json. If it's a transitive dependency patch-package can't detect that it is safe to ignore and will throw an error. To fix this, mark patches for transitive dev dependencies as dev-only by renaming from, e.g.

package-name+0.44.0.patch

to

package-name+0.44.0.dev.patch

This will allow those patch files to be safely ignored when NODE_ENV=production.

Creating multiple patches for the same package

💡 This is an advanced feature and is not recommended unless you really, really need it.

Let's say you have a patch for react-native called

  • patches/react-native+0.72.0.patch

If you want to add another patch file to react-native, you can use the --append flag while supplying a name for the patch.

Just make you changes inside node_modules/react-native then run e.g.

npx patch-package react-native --append 'fix-touchable-opacity'

This will create a new patch file while renaming the old patch file so that you now have:

  • patches/react-native+0.72.0+001+initial.patch
  • patches/react-native+0.72.0+002+fix-touchable-opacity.patch

The patches are ordered in a sequence, so that they can build on each other if necessary. Think of these as commits in a git history.

Updating a sequenced patch file

If the patch file is the last one in the sequence, you can just make your changes inside e.g. node_modules/react-native and then run

npx patch-package react-native

This will update the last patch file in the sequence.

If the patch file is not the last one in the sequence you need to use the --rebase feature to un-apply the succeeding patch files first.

Using the example above, let's say you want to update the 001+initial patch but leave the other patch alone. You can run

npx patch-package react-native --rebase patches/react-native+0.72.0+001+initial.patch

This will undo the 002-fix-touchable-opacity patch file. You can then make your changes and run

npx patch-package react-native

to finish the rebase by updating the 001+initial patch file and re-apply the 002-fix-touchable-opacity patch file, leaving you with all patches applied and up-to-date.

Inserting a new patch file in the middle of an existing sequence

Using the above example, let's say you want to insert a new patch file between the 001+initial and 002+fix-touchable-opacity patch files. You can run

npx patch-package react-native --rebase patches/react-native+0.72.0+001+initial.patch

This will undo the 002-fix-touchable-opacity patch file. You can then make any changes you want to insert in a new patch file and run

npx patch-package react-native --append 'fix-console-warnings'

This will create a new patch file while renaming any successive patches to maintain the sequence order, leaving you with

  • patches/react-native+0.72.0+001+initial.patch
  • patches/react-native+0.72.0+002+fix-console-warnings.patch
  • patches/react-native+0.72.0+003+fix-touchable-opacity.patch

To insert a new patch file at the start of the sequence, you can run

npx patch-package react-native --rebase 0

Which will un-apply all patch files in the sequence. Then follow the process above to create a new patch file numbered 001.

Deleting a sequenced patch file

To delete a sequenced patch file, just delete it, then remove and reinstall your node_modules folder.

If you deleted one of the patch files other than the last one, you don't need to update the sequence numbers in the successive patch file names, but you might want to do so to keep things tidy.

Partially applying a broken patch file

Normally patch application is atomic per patch file. i.e. if a patch file contains an error anywhere then none of the changes in the patch file will be applied and saved to disk.

This can be problematic if you have a patch with many changes and you want to keep some of them and update others.

In this case you can use the --partial option. Patch-package will apply as many of the changes as it can and then leave it to you to fix the rest.

Any errors encountered will be written to a file ./patch-package-errors.log to help you keep track of what needs fixing.

Benefits of patching over forking

  • Sometimes forks need extra build steps, e.g. with react-native for Android. Forget that noise.
  • Get told in big red letters when the dependency changed and you need to check that your fix is still valid.
  • Keep your patches colocated with the code that depends on them.
  • Patches can be reviewed as part of your normal review process, forks probably can't

When to fork instead

  • The change is too consequential to be developed in situ.
  • The change would be useful to other people as-is.
  • You can afford to make a proper PR to upstream.

Isn't this dangerous?

Nope. The technique is quite robust. Here are some things to keep in mind though:

  • It's easy to forget to run yarn or npm when switching between branches that do and don't have patch files.
  • Long lived patches can be costly to maintain if they affect an area of code that is updated regularly and you want to update the package regularly too.
  • Big semantic changes can be hard to review. Keep them small and obvious or add plenty of comments.
  • Changes can also impact the behaviour of other untouched packages. It's normally obvious when this will happen, and often desired, but be careful nonetheless.

Why use postinstall-postinstall with Yarn?

Most times when you do a yarn, yarn add, yarn remove, or yarn install (which is the same as just yarn) Yarn will completely replace the contents of your node_modules with freshly unpackaged modules. patch-package uses the postinstall hook to modify these fresh modules, so that they behave well according to your will.

Yarn only runs the postinstall hook after yarn and yarn add, but not after yarn remove. The postinstall-postinstall package is used to make sure your postinstall hook gets executed even after a yarn remove.

License

MIT

Empowered by Futurice's open source sponsorship program

changelog

Changelog

8.0.0

  • Add support for multiple patch files for a single package. #474

7.0.2

  • Bump semver again (contribution from @rsanchez in #477)

7.0.1

  • Bump semver (contribution from @stianjensen in #466)

Breaking changes

  • Bump yaml to fix security issue. Required bumping minimum node version from 8 to 14. (contribution from @mayank99 in #463)

Other changes

  • Bump cross-spawn (contribution from @stianjensen in #457)
  • Replace is-ci with ci-info (contribution from @paescuj in #446)
  • Make version number parsing more robust (contribution from @MHekert in #361)

6.5.1

Special thanks to @orta again for putting this release together.

  • Improve error message for missing lockfile entry (contribution from @Andarist and @farskid in #439)
  • Fix creating patches for github dependencies (contribution from @dijonkitchen in #444)
  • Improve yarn 2 support by copying .yarn dir when creating patch (contribution from @bdwain in #438)
  • Upgrade fs-extra (contribution from @stianjensen in #441)
  • Add support for nmp lockfile v2 (contribution from @anas10 in #434)

6.5.0

Special thanks to @orta for stepping in to get this release out.

  • Don't show issue creation tips for DefinitelyTyped (contribution from @orta in

    331)

  • Add --error-on-warn flag (contribution from @mvargeson in #345)
  • Add excplit git diff path prefixes (contribution from @tye-singwa in #395)
  • Add yarn 2 compatibility (contribution from @maman in #363)
  • Update license (contribution from @Serjobas in #422)
  • Fix patch file parse but (contribution from @bill2004158 in #301)
  • Add unit tests for getPackageVersion (contribution from @MHekert in #359)
  • Deref symlink on copying .npmrc and .yarnrc in makePatch (contribution from @jimmyltsinn in 402)
  • Fix package.json exclusion (contribution from @milahu in #390)
  • Upgrade minimist (contribution from @tapanprakasht in #412)
  • Upgrade chalk (contribution from @stianjensen in #389)
  • Support .yarnrc (contribution from @NMinhNguyen in #222)

6.4.7

  • Use npm i --force when creating patches

6.4.6

  • Update find-yarn-workspace-root (contribution from @sarimarton in #282)
  • Fix rare npm crash when creating patches (contribution from @kf6kjg in #271)

6.4.5

  • Increase max pipe buffer size when creating patch. (contribution from @nomi9995 in #287)

6.4.4

  • Refine --create-issue template

6.4.3

  • Ensure real path is used when copying package contents. Potentially adds pnpm support (contribution from @milahu in #252)

6.4.2

  • Add package version to --create-issue template

6.4.1

  • Add backlink to patch-package repo to collect public usage of --create-issue

6.4.0

  • Add --create-issue option

6.3.1

  • Fix another createPatch bug involving .git folder hygiene (contribution from @gomain in #258)

6.3.0

  • Add --error-on-fail cli option
  • Collate errors and warnings to avoid exiting early (with help from @akwodkiewicz in #217)
  • Fix .dev.patch suffix bug (with help from @pdcastro in #224)
  • Support build metadata in package.json version strings (with help from @snowystinger in #213)
  • Change 'no patch files found' message from red to blue (contribution from @dmhalejr in #211)
  • Fix environment variable propogation for spawned tasks (contribution from @chpio in #223)
  • Add --patch-dir option to readme (contribution from @mikehardy in #225)
  • Fix createPatch bug involving .git folder hygiene (contribution from @haroenv in #231)

6.2.2

  • Take config from .yarnrc when making patches (contribution from @NMinhNguyen in #222)

6.2.1

  • Avoid infinite loop when invoked without package.json
  • Fall back to version in package-lock (contribution from @bschlenk in #206)
  • Add tips about Docker and CI to README (contribution from @harriha in #208)
  • Remove update notifier (contribution from @christianbundy in #196)
  • Add github actions checks (contribution from @asadm in #186 and @DanielRuf in

    188, #187)

  • Fix url in README (contribution from @DanielRuf in #184)
  • Upgrade node in CI to 12 (contribution from @DanielRuf in #183)

6.2.0

  • Add support for dev-only patches (#159 again)

6.1.4

  • Use --ignore-scripts when making patches if it fails without (#151)

6.1.3

  • Fail when patches are found for uninstalled packages (#159)
  • Support private registries declared in .npmrc (Contribution from @cherniavskii in #152)

6.1.2

  • Explicitly handle failure edge case where symlinks are modified/created (#118)

6.1.1

  • Fix npm edge case of package installed from url (#134)

6.1.0

  • Add support for yarn workspaces
  • Degrade 'file mode change not required' error to warning

6.0.7

  • Don't try to detect package manager on patch application (#133)

6.0.6

  • Better error messages for patch parse failures (#131)

6.0.5

  • Use lockfiles to get package resolutions.

6.0.4

  • Fix patch parsing issue affecting windows (#124)

6.0.3

  • Allow relative file paths for --patch-dir (Contribution from @lots0logs in

    119)

  • Fix version string handling (Contribution from @teppeis in #122)
  • Add support for custom resolutions field in app's package.json (#125)
  • Fix property access bug (#123)
  • Move @types/is-ci from dependencies to devDependencies (#121)

6.0.2

  • Revert failure exit code when no patches are found.

6.0.1

  • Document --patch-dir option in readme

6.0.0

Highlights!

  • No longer dependent on Git to apply patches
  • Patch files are created much much much faster 🏃🏽‍♀️💨
  • Fixed lots of small bugs
  • Explicit support for nested packages

For full details see the prerelease notes.

6.0.0-18

  • Allow fuzzy patch hunk application.
  • Minor UI tweaks
  • Ignore global git config to prevent issues like #109 & #115
  • Add --ignore-engines to yarn invocation

6.0.0-17

  • Fix the removal of old patch files when creating new ones.

6.0.0-16

  • Fail postinstall only on CI to prevent weird upgrade issues locally (see #86)
  • Fail if no patches are present

6.0.0-15

  • Handle mode changes
  • Backwards-compatible patch file parsing

6.0.0-14

  • Handle renaming files properly

6.0.0-13

  • Handle large diffs by not calling .toString on stdout buffer
  • Git usage fixes

6.0.0-12

  • Support explicit nested package patching
  • Improve performance of patch creation

6.0.0-11

  • Handle crlf line breaks in patch parser (Contribution from @NMinhNguyen)

6.0.0-10

  • Add --patches-dir option (Contribution from @davidpett)

6.0.0-9

  • Fix patch application bug when creating new files (Contribution from @stmarkidis)

6.0.0-8

  • Improve diffing speed (Contribution from @KevinVlaanderen)

6.0.0-7

  • Use --no-ext-diff option when generating diffs (Contribution from @janv)

6.0.0-6

  • Make include/exclude regexes applied relative to the package root. Fixes #54

6.0.0-5

  • Fix preventing scripts from running when making patch file

6.0.0-4

  • Don't delete package.json during patch creation

6.0.0-3

  • Bugfixes for patch application
  • Prevent scripts from running when making patch file

6.0.0-2

  • Bugfixes for patch application

6.0.0-1

  • Bugfixes for patch application

6.0.0-0

  • Reimplement most of patch application in TypeScript

5.1.1

  • Fix idempotency regression. See #39

5.1.0

  • Add --reverse option for patch application. See #37

5.0.0

  • Remove yarn patching code
  • Recommend postinstall-prepare in README for yarn compatibility

4.0.0

  • Ignore all package.json files by default
  • Exit with appropriate error when git is not available

3.6.1

  • Fix bug where patch-package was complaining about failing when it had, in fact, succeeded. See #31

3.6.0

  • Remove git headers from patch files to prevent git from thinking files are part of the index

3.5.3

  • Change the way patch files are re-written when the project root dir is not the same as the git root dir.
  • Remove redundant windows warning about whitespace

3.5.2

  • Update README

3.5.1

  • Ignore end-of-line whitespace when creating and applying patch files

3.5.0

  • Add support for filtering particular paths

3.4.6

  • Ensure use of unix-style paths everywhere

3.4.5

  • Fix description of a hunk in error message

3.4.4

  • Don't use git apply with --unsafe-paths since it is useless.

3.4.3

  • Fix typo in error message

3.4.2

  • Revert previous fix and suggest editing .gitattributes as an alternative

3.4.1

  • Fix CRLF handling on Windows

3.4.0

  • Add npm shrinkwrap support

3.3.6

  • Use posix paths and line separators even on windows, for git's sake.

3.3.5

  • Resolve paths in patch files for situations where the git root is not the same as the app root.

3.3.4

  • Pass --unsafe-paths option to git apply to let it work on arbitrary file paths (i.e. files which are not in a git repo or files which are outside of the working directory)

3.3.3

  • Fix bug introduced in 3.3.2
  • Add progress reporting during patch making

3.3.2

Windows fixes:

  • Use cross-spawn for spawning child processes
  • Use git apply for applying patches, rather than patch

Contribution by @ashmind

3.3.1

  • Use fs-extra to copy files instead of the cp shell command, which doesn't work on Windows

3.3.0

  • Use + instead of : in patch file names because : is illegal on Windows.

3.2.1

  • Make update-notifier message show local install

3.2.0

  • Add update-notifier to notify users of patch-package updates

3.1.0

  • Add support for scoped packages

3.0.0

  • Add support for npm5
  • Make yarn patching a cli option, off by default

2.1.1

Improve error messages

2.1.0

Reduce yarn error to a warning

2.0.0

  • Require yarn as a peer dependency
  • Remove support for NPM

Moving fast and breaking things. It turns out yarn doesn't run the prepare hook after removing a package, so we use patch-package to patch a local version of yarn. I'm not proud of this. Probably wouldn't have released this in the first place if I had known that yarn didn't have all the right hooks. Oh well. Now I have a reason to contribute to Yarn I guess.

1.2.1

  • Fix patch creation logic around nested node_modules

1.2.0

  • Enable picking up changes in nested node_modules folders.
  • Enable adding new files, not just patching existing files.

1.1.1

  • Fix bug that made exit code 1 regardless of success or failure.

1.1.0

  • Make applying patches work
  • Add nice colorful log messages.

1.0.0

Initial broken release