A smart, context-aware patch tool for the modern developer.
mpatch
applies unified diffs to your codebase, but with a twist. Instead of relying on strict line numbers, it finds the correct location to apply changes based on the surrounding context. It's designed to work seamlessly with patches generated by AI, copied from pull requests, or stored in markdown files.
The primary motivation for mpatch
comes from working with Large Language Models (LLMs).
When you ask an AI like ChatGPT, Claude, or Copilot to refactor code, it often provides the changes in a convenient markdown format with ```diff
blocks. However, you can't trust that the line numbers are correct. Sometimes, even the surrounding context lines aren't a perfect, character-for-character match to your current code. A standard patch
command will often fail in these situations.
This is the core problem mpatch
was built to solve.
It intelligently ignores line numbers and uses a fuzzy, context-based search to find where the patch should apply. This makes it highly resilient to the small inaccuracies common in AI-generated diffs, allowing you to apply them with confidence.
This same logic makes it perfect for other common developer scenarios where patches are less formal:
- Code Snippets: Using a diff copied from a GitHub comment, a blog post, or a team chat.
- Iterative Development: Applying a patch to a branch that has slightly diverged from where the patch was created.
- Markdown-Aware: Directly parses unified diffs from within ````diff ` code blocks in any text or markdown file.
- Context-Driven: Ignores
@@ ... @@
line numbers, finding patch locations by matching context lines. This makes it resilient to minor preceding changes in a file. - Fuzzy Matching: If an exact context match isn't found,
mpatch
can use a similarity algorithm to find the best fuzzy match, allowing patches to apply even if the source has slightly diverged. - Safe & Secure: Includes a
--dry-run
mode to preview changes and built-in protection against path traversal attacks. - Flexible: Handles multiple files and multiple hunks in a single pass. It correctly processes file creations, modifications, and deletions (by removing all content from a file).
- Informative Logging: Adjustable verbosity levels (
-v
,-vv
) to see exactly whatmpatch
is doing.
For users who don't need to build from source, pre-compiled binaries are the simplest option.
- Navigate to the GitHub Releases page.
- Download the appropriate archive for your system (e.g.,
mpatch-x86_64-unknown-linux-gnu.tar.gz
). - Extract the
mpatch
executable. - Move the executable to a directory in your system's
PATH
(e.g.,/usr/local/bin
on Linux/macOS, or~/.cargo/bin
).
If you have the Rust toolchain installed, you can install mpatch
directly from the official package registry:
cargo install mpatch
To build the very latest development version or to contribute to the project:
# Install directly from the main branch of the repository
cargo install --git https://github.com/romelium/mpatch.git
# Or, to work on the code locally:
git clone https://github.com/romelium/mpatch.git
cd mpatch
cargo install --path .
mpatch [OPTIONS] <INPUT_FILE> <TARGET_DIR>
Before modifying any files, you can preview the exact changes using the -n
or --dry-run
flag. This is the safest way to start.
mpatch --dry-run changes.md my-project/
This will produce a diff of the proposed changes for each file, printed directly to your terminal:
----- Proposed Changes for src/main.rs -----
--- a
+++ b
@@ -1,5 +1,5 @@
fn main() {
- // This is the original program
- println!("Hello, world!");
+ // This is the updated program
+ println!("Hello, mpatch!");
}
------------------------------------
DRY RUN completed. No files were modified.
Once you are confident in the proposed changes, run the command without --dry-run
. Use -v
for informational output.
mpatch -v changes.md my-project/
You will see a confirmation log:
Found 1 patch operation(s) to perform.
Fuzzy matching enabled with threshold: 0.70
>>> Operation 1/1
Applying patch to: src/main.rs
Applying Hunk 1/1...
Successfully wrote changes to 'my-project/src/main.rs'
--- Summary ---
Successful operations: 1
Failed operations: 0
-n
,--dry-run
: Show what changes would be made without modifying any files.-f
,--fuzz-factor <FACTOR>
: Set the similarity threshold for fuzzy matching, from0.0
(disabled) to1.0
(exact match). Default is0.7
.-v
,--verbose
: Increase logging output. Use-v
for general info,-vv
for debug details, and-vvv
for trace-level inspection.
This project is licensed under MIT LICENSE
Contributions are welcome! Feel free to open an issue or submit a pull request.