gitpatchgit-am

Git: patch cannot apply - missing header info


I'm getting this error when trying to apply a patch using git am:

error: git diff header lacks filename information
when removing 1 leading pathname component (line 9)

The patch was created using git's own format-patch command and not edited in any way, what's wrong?


Solution

  • but apparently git patches rely on them.

    It should no longer be an issue:

    With Git 2.41 (Q2 2023), "git format-patch"(man) honors the src/dst prefixes set to nonstandard values with configuration variables like diff.noprefix, causing the receiving end of the patch that expects the standard -p1 format to break.
    Teach "format-patch" to ignore end-user configuration and always use the standard prefixes.

    This is a backward compatibility breaking change.

    See commit ab89575 (13 Mar 2023), and commit 8d5213d, commit c169af8, commit b39a569, commit 7c03d0d, commit 6799aad (09 Mar 2023) by Jeff King (peff).
    (Merged by Junio C Hamano -- gitster -- in commit 15108de, 21 Mar 2023)

    format-patch: do not respect diff.noprefix

    Signed-off-by: Jeff King

    The output of format-patch respects diff.noprefix, but this usually ends up being a hassle for people receiving the patch, as they have to manually specify "-p0" in order to apply it.

    I don't think there was any specific intention for it to behave this way.
    The noprefix option is handled by git_diff_ui_config(), and format-patch exists in a gray area between plumbing and porcelain.

    People do look at the output, and we'd expect it to colorize things, respect their choice of algorithm, and so on.
    But this particular option creates problems for the receiver (in theory so does diff.mnemonicprefix, but since we are always formatting commits, the mnemonic prefixes will always be "a/" and "b/").

    So let's disable it.
    The slight downsides are:

    • people who have set diff.noprefix presumably like to see their patches without prefixes.
      If they use format-patch to review their series, they'll see prefixes.
      On the other hand, it is probably a good idea for them to look at what will actually get sent out.

      We could try to play games here with "is stdout a tty", as we do for color.
      But that's not a completely reliable signal, and it's probably not worth the trouble. If you want to see the patch with the usual bells and whistles, then you are better off using "git log" or "git show".

    • if a project really does have a workflow that likes prefix-less patches, and the receiver is prepared to use "-p0", then the sender now has to manually say "--no-prefix" for each format-patch invocation.
      That doesn't seem too terrible given that the receiver has to manually say "-p0" for each git-am(man) invocation.

    And:

    format-patch: add format.noprefix option

    Signed-off-by: Jeff King

    The previous commit dropped support for diff.noprefix in format-patch.
    While this will do the right thing in most cases (where sending patches without a prefix was an accidental side effect of the sender preferring to see their local patches without prefixes), it left no good option for a project or workflow where you really do want to send patches without prefixes.
    You'd be stuck using "--no-prefix" for every invocation.

    So let's add a config option specific to format-patch that enables this behavior.
    That gives people who have such a workflow a way to get what they want, but makes it hard to accidentally trigger it.

    A more backwards-compatible way of doing the transition would be to have format.noprefix default to diff.noprefix when it's not set.
    But that doesn't really help the "accidental" problem; people would have to manually set format.noprefix=false.
    And it's unlikely that anybody really wants format.noprefix=true in the first place.
    I'm adding it here mostly as an escape hatch, not because anybody has expressed any interest in it.

    git config now includes in its man page:

    format.noprefix

    If set, do not show any source or destination prefix in patches. This is equivalent to the diff.noprefix option used by git diff (but which is not respected by format-patch). Note that by setting this, the receiver of any patches you generate will have to apply them using the -p0 option.