PHPackages                             gwsmedia/composer-patch-manager - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [CLI &amp; Console](/categories/cli)
4. /
5. gwsmedia/composer-patch-manager

ActiveLibrary[CLI &amp; Console](/categories/cli)

gwsmedia/composer-patch-manager
===============================

composer-patches improved! A plugin for applying composer patches heuristically.

24PHP

Since May 25Pushed 2y agoCompare

[ Source](https://github.com/gwsmedia/composer-patch-manager)[ Packagist](https://packagist.org/packages/gwsmedia/composer-patch-manager)[ RSS](/packages/gwsmedia-composer-patch-manager/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependenciesVersions (1)Used By (0)

Composer Patch Manager
======================

[](#composer-patch-manager)

The aim of this plugin is to be able to easily generate and apply patches in conjunction with composer.

Any changes already made to a package can be saved to a patch file, and then re-applied either manually or automatically when the package is updated or reinstalled.

Difference to [composer-patches](https://github.com/cweagans/composer-patches)?
-------------------------------------------------------------------------------

[](#difference-to-composer-patches)

**composer-patches** is a great plugin if you want to simply apply *existing* patches to the *same* version of a package.

CPM will both generate these patches for you if desired, but also will heuristically make more efforts to apply the patch if a new version has changed the code and it struggles to apply initially.

The generated patches and `composer-patches.json` file are both compatible with **composer-patches**, so it is easy to transition to/from either plugin. Please note that at the moment CPM only supports *local* patches.

Requirements
------------

[](#requirements)

This plugin requires that you have `git`, `php`, and `composer` installed, and the PHP `exec()` function is enabled on the CLI.

If you are on a server and any of these are not available and cannot be installed it is advisable to use this plugin *locally* and upload any changes.

Installation
------------

[](#installation)

`composer require gwsmedia/composer-patch-manager`

If you would like CPM to automatically apply patches the following command will add the necessary hooks: `vendor/bin/cpm init`

If you would like to *only* apply patches on install or only on update, after running the command above, within `composer.json` remove the ComposerPatchManager hook in `post-package-install` or `post-package-update`, respectively.

Usage
-----

[](#usage)

### Generating patches

[](#generating-patches)

Make any necessary changes to packages installed with composer (in `vendor/` or at the destination defined in `installer-paths` in your `composer.json`).

Then define the packages you would like to generate patches for in `composer-patches.json`:

```
{
	"packages": ["vendor/package"]
}

```

When ready, run `vendor/bin/cpm generate`.

CPM will run through each defined package, output a patch file to `patch/vendor--package.patch`, and update `composer-patches.json` with a path to this file.

All changes are captured collectively in a singular patch file for each package, so feel free to make amendments and then regenerate.

### Applying patches

[](#applying-patches)

Any patch files defined in `composer-patches.json` will be applied. If generated with the command above, they will automatically be added to the config file, but other patches can be added as well:

```
{
	"patches": {
		"vendor/project": {
			"Patch title: "patch/custom.patch"
		}
	}
}

```

Now, if you ran `vendor/bin/cpm init`, CPM will attempt to apply these patches whenever the relevant package is installed or updated.

If you would like to do a one time run use: `vendor/bin/cpm apply`.

#### Patching process

[](#patching-process)

CPM uses the following heuristic methodology for applying patches (using `git diff --no-index`):

1. Attempt to apply patch normally
2. Then, attempt with `--recount` (ignoring line numbers)
3. Then, attempt with `-C1` (only using 1 line of context either side)
4. Finally, if still failing, attempt with `--reject` which will apply any hunks in a patch it can, and failed hunks will be stored in `.rej` files.
    - CPM will run a **dry run** of this command and ask the user if they would like to proceed before making the changes.
    - It will then show the user a list of all the rejected hunks.
    - **Please note:** if you proceed with this method, not all of the changes in the patch file will be applied, so make sure no code within the patch relies on the rejected hunks. If so, it is best to do this *locally*, apply the rejected hunks manually, test, and then upload.

Example composer-patches.json
-----------------------------

[](#example-composer-patchesjson)

```
{
	"packages": ["psr/container", "drupal/quiz"],
	"patches": {
		"psr/container": {
			["patch/psr--container.patch"]
		},
		"drupal/quiz": {
			[
				"patch/drupal--quiz.patch",
				"patch/external.patch"
			]
		}
	}
}

```

Known issues
------------

[](#known-issues)

- At the moment, you must only run `/vendor/bin/cpm` commands in the root project directory (where composer.json and composer.lock are defined)
- `repositories` defined in composer.json that use `type: path` and a relative path will break the `generate` command
- All patches must be relative to the project root - this is not ideal for patches downloaded from drupal.org for example which will be relative to the package folder, but this can be worked around by applying the patch manually, and then running the `generate` command to include it in the collective patch file.

###  Health Score

14

—

LowBetter than 2% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity6

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity22

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/e564dfbf1368cae673551fa1e34185b8e58e0d5d2fb39296dd765299d01e315e?d=identicon)[JeromeGWS](/maintainers/JeromeGWS)

---

Top Contributors

[![JeromeBeckett](https://avatars.githubusercontent.com/u/43885091?v=4)](https://github.com/JeromeBeckett "JeromeBeckett (30 commits)")

---

Tags

clicomposergitpatchphp

### Embed Badge

![Health badge](/badges/gwsmedia-composer-patch-manager/health.svg)

```
[![Health](https://phpackages.com/badges/gwsmedia-composer-patch-manager/health.svg)](https://phpackages.com/packages/gwsmedia-composer-patch-manager)
```

###  Alternatives

[wp-cli/wp-cli

WP-CLI framework

5.0k17.2M319](/packages/wp-cli-wp-cli)[consolidation/annotated-command

Initialize Symfony Console commands from annotated command class methods.

22569.8M18](/packages/consolidation-annotated-command)[chi-teck/drupal-code-generator

Drupal code generator

26947.8M5](/packages/chi-teck-drupal-code-generator)[seld/cli-prompt

Allows you to prompt for user input on the command line, and optionally hide the characters they type

24725.8M17](/packages/seld-cli-prompt)[illuminate/console

The Illuminate Console package.

12944.1M5.1k](/packages/illuminate-console)[php-tui/php-tui

Comprehensive TUI library heavily influenced by Ratatui

589747.0k6](/packages/php-tui-php-tui)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
