Handling Rejects

How to deal with patches that don't apply cleanly.

1. What are rejects?

Rejects are pieces of a patch that don't apply cleanly. Because patches are a traditional format for exchanging code changes, they lack some of the information needed to smoothly integrate when conflicting changes are made.

Here's an example scenario. Alice has a hello-world that contains the following hello.c:

#include <stdio.h>

int main(void)
{
        printf("Hello, world\n");
}

She publishes it, Bob downloads it, and sends her the following patch:

Here's a punctuation fix for you:

diff -r 363482718c56 hello.c
--- a/hello.c   Wed Oct 20 17:19:51 2010 -0500
+++ b/hello.c   Wed Oct 20 17:21:41 2010 -0500
@@ -2,5 +2,5 @@
 
 int main(void)
 {
-       printf("Hello, world\n");
+       printf("Hello, world.\n");
 }

Meanwhile, Alice has fixed the missing return statement in her code:

#include <stdio.h>

int main(void)
{
        printf("Hello, world\n");
        return 0;
}

Now when she goes to apply the patch, she gets:

$ hg import bob.patch 
applying bob.patch
patching file hello.c
Hunk #1 FAILED at 1
1 out of 1 hunks FAILED -- saving rejects to file hello.c.rej
abort: patch failed to apply

This happened because the context around Bob's patch has changed since Bob sent the patch. The patch process stores the conflicting 'patch hunks' for each problem file in a corresponding .rej file. In this case, because Bob's patch only had one hunk, it's the same as his original patch.

2. Manually fixing up rejects

Often, the simplest way to deal with rejects is to open all the resulting .rej files and their corresponding source files in an editor and manually apply the changes from the reject one by one. With a unified diff, the reject will show context around the change as well as hunk headers to help you locate the lines you need to change:

@@ -2,5 +2,5 @@

For larger patches, this can be a tedious process and some tools may be helpful:

3. Getting help from Mercurial

If you know what version of a project a patch applies to, you can get help from Mercurial. In our example, Alice knows that the patch applies to her first commit:

$ hg up 0
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg import --no-commit bob.patch
applying bob.patch

Here the patch applied cleanly to her earlier version, leaving the changes in her working directory. Now all that's needed is to update back to the project tip to incorporate Bob's changes:

$ hg up
merging hello.c
0 files updated, 1 files merged, 0 files removed, 0 files unresolved

The merge succeeded without conflicts, so Alice can commit Bob's changes:

$ hg ci -m "Punctuation fix" -u bob

You can also use a normal import and a merge if it's more convenient.

It may not always be possible to tell which version of a project a patch applies to. If a patch was generated by 'hg export', it will include a 'parent' header that contains the right version. Otherwise a little guesswork with update and import should suffice.

4. Rejects when working with MQ

Applying patches to different points of the tree is a frequent operation when working with the MQ extension, and regularly results in rejects. One of the easiest ways to deal with this is to 'rebase' your MQ stack with the rebase extension.

5. See also


CategoryHowTo

HandlingRejects (last edited 2012-03-09 01:13:48 by mpm)