Re: git-am failed, what's next ?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



"git-am" deserves a section in the user-manual on its own.
Perhaps the following can be massaged into JBF's User Manual,
but probably with copyediting and spellfixes.

First, the basics.
------------------

When "git am ./mbox" stops in the middle, you will find
these files in the .dotest/ directory:

0002 0003 0004...::

        Numbered files are split e-mails, yet to be applied, and
        the first one is the one that failed to apply.  Already
        applied ones are removed so they may not begin with
        0001.

next, last::

        These files are used to control sequencing.  'next' is
        the patch you are applying, and 'last' is the number of
        the last patch in the series.

info msg msg-clean final-commit patch::

        These files record information of the patch you are
        applying.  'info' lists the metainformation for the
        commit to be made, 'msg' is the raw message extracted
        from e-mail, 'msg-clean' is a copy of it after stripping
        excess whitespaces, and 'final-commit' is after adding
        sign-off lines (when -s is given).  'patch' is the patch
        text itself.

There are two strategies to resume an "am" that stopped because
a patch does not apply.

One is to fix the patch into applicable shape in whatever way
you can think of, and attempt to apply it again, with "git am".

The other is to update your index to the desired state after
applying the given patch in whatever way you can think of, and
continue with "git am --resolved".

You can also choose not to continue, but skip one patch.  You
can say:

	$ git reset --hard
        $ git am --skip

to skip that particular patch.  This advances 'next' and
continues with the remainder.

[jc: I think that is not what you want in your RFH, but I am
spelling it out for inclusion in the User Manual -- this comment
itself should be removed if somebody wants to include this
message to the manual.]

Now, let's go on to "whatever way you can think of".


Fixing patch text
-----------------

Linus's way is to visit the ./mbox file in the editor, remove
the messages that have already been applied cleanly, edit the
offending patch text to make it applicable.  Then:

	$ git reset --hard
        $ rm -fr .dotest
        $ git am edited-mailbox-file

A variant of this approach is to edit .dotest/patch to make it
applicable, and then say (without removing .dotest/ directory,
of course):

	$ git am

But these are probably reserved for people who are comfortable
editing the patch text.


Applying by hand
----------------

If you (as most people) are not comfortable editing the patch
text you can update your working tree to pretend that the patch
applied cleanly.  You can do number of things:

 * Use "git apply --index -C<n> .dotest/patch" to attempt
   applying the patch with reduced context.

 * Use "git apply --reject .dotest/patch" to get apply only
   hunks that apply cleanly, while getting *.rej files.

 * Use "GNU patch" with less strict options, perhaps like

	$ patch -p1 --fuzz=<n> --ignore-whitespace

Whatever you do, do not forget that your goal with this strategy
is to prepare your index into a shape that the patch should have
made it into, if it applied cleanly.  In other words, after you
are done, "git diff --cached HEAD" should produce what the
original patch in .dotest/patch should have contained.  Also,
typically, "git diff" at that point should say nothing (unless
you know what you are doing).

So, if you used "git apply" without --index (or plain "GNU
patch"), do not forget to "git add" to register the result in
the index.  Especially, if the patch adds a new file, do not
forget to include it in the index!

After you are done, you would continue with:

	$ git am --resolved


Letting git work harder
-----------------------

It _could_ be that the original submitter prepared the patch to
a different branch of your repository than the branch you are
trying to apply the patch to.  Sometimes I get a patch that is
against my 'next' but the change does not depend on what is only
in 'next' and should be applied to 'master' (or even 'maint').
If you have the pre-image blobs the patch was created against,
and the patch was created with git and records "index" lines
like these correctly:

        diff --git a/builtin-config.c b/builtin-config.c
        index 0f9051d..f1433a4 100644

then you can tell git to fall back on 3-way merge to apply the
patch.  After seeing "git am ./mbox" fail, you could try
(without doing anything else):

	$ git am -3

This can result in one of three things:

 * It can complain, with "Patch does not record usable index
   information".  When this happens, you are back to square-one.
   Your repository does not have enough blobs for it to fall
   back on 3-way merge.  The operation did not change anything
   in your working tree nor what are in .dotest/ directory, so
   it did not do any further harm.  You have to use one of the
   two strategies described above instead.

 * It can successfully fall back on 3-way merge and cleanly
   apply the patch.  Lucky you.

 * It can fall back on 3-way merge but the merge can conflict.

In the third case, the usual conflict resolution techniques you
would use during a conflicted merge applies, except that you do
NOT conclude it with "git commit".

This "3-way" is in fact a variant of "Applying by hand"
strategy, and your goal is still to update the index into the
shape the original patch should have made into.  After you
resolve the conflict, you do "git add" the resolved path (or if
the patch is about removing a path and if you do want to remove
that path, then "git rm").  Make sure that "git diff --cached
HEAD" output matches what you think .dotest/patch should have
contained.  Then:

	$ git am --resolved

to continue.

-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]