1

I have a patch file which contains a single line change. Running git am fails with the message:

error: patch failed: Pages/Index.cshtml.cs:15
error: Pages/Index.cshtml.cs: patch does not apply
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Applying: restrict index page to internal users
Patch failed at 0001 restrict index page to internal users
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".

The target file does have a couple of extra lines above the changed line. Is this failing because git cannot determine where the single line change? If so, does this mean that the target file and source file need to be essentially the same?

Running git apply with the same patch produced this message:

error: patch failed: Pages/Index.cshtml.cs:15
error: Pages/Index.cshtml.cs: patch does not apply

I believe this is basically the same message, just friendly (or, at least, less verbose.)

Am I attempting something which patches are not meant for? Namely, applying a change from one repository to another which are not possessing file content equivalence.

I did find this post but when using the same solution all I get is no change and a simple .rej file output.

Matt W
  • 11,753
  • 25
  • 118
  • 215
  • Is the patch from the same repo/branch or something totally unrelated? What happens if you `Use 'git am --show-current-patch=diff' to see the failed patch`? Or perhaps do `git am -3`? – underscore_d Jun 17 '20 at 15:30
  • The target solution is actually a copy of the source, with only a few changes over the last month or so. I'm afraid I am new to git patch. The diff just tells me the patch failed and which file it was; Nothing the apply didn't tell me. What does 'git am -3' do? (I am sort of assuming that if I am taking commits from one [very] similar solution they should work.) – Matt W Jun 17 '20 at 15:39
  • `git am -3` does what the documentation says :-) or what torek explained. If it doesn't work any better, you don't stand to lose anything, so just try it. – underscore_d Jun 18 '20 at 08:48

1 Answers1

3

The target file does have a couple of extra lines above the changed line. Is this failing because git cannot determine where the single line change?

Yes, that is the case. Git checks not only the specific change (add this, delete that) but also the context in which the change occurs. If the context does not match, the patch does not apply.

Using -3 or --3way can help: the idea behind this option is that if the patch was made to a version of the file that you do have, in your Git repository, Git can extract that version of the file, compare that version to the current version, see what has changed in your copy of the file, and combine (as in, git merge style operations) your changes and their changes. Pictorially, imagine this:

...--o--o--B--o--o--o--C   <-- your current commit and copy of the file
            \
             D   <-- the commit from which the patch was generated

Commit B is the base version, which your commit C and their commit D shared. The patch changes the base version of the file. Your commit C has a different version of the same file, but by comparing D vs B—i.e., what's in the patch—and comparing C vs B at the same time, Git may be able to figure out, on its own, how to apply the patch after all.

The trick here is to understand where Git comes up with the file from commit B. The answer to that is in the index line, if there is one, in the patch. The index gives Git the information needed to find the copy of the file that would be in commit B—provided, of course, that you actually have that copy of the file in your repository.

torek
  • 448,244
  • 59
  • 642
  • 775