{"thread":{"id":"58100","subject":"Why `git am -3` apply patches that don't normally apply?","startedAt":"2022-07-03T12:12:01Z","lastAt":"2022-07-06T00:19:15Z","messageCount":4,"participants":["Yuri Kanivetsky","Elijah Newren","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"458432","messageId":"CAMhVC3Z92hBsK0FbE4E_LV1CSxjR1zmu+MO8=iwR02BKqnwgUA@mail.gmail.com","threadId":"58100","inReplyTo":null,"subject":"Why `git am -3` apply patches that don't normally apply?","fromName":"Yuri Kanivetsky","fromEmail":"yuri.kanivetsky@gmail.com","sentAt":"2022-07-03T12:11:46Z","receivedAt":"2022-07-03T12:12:01Z","isPatch":false,"sender":{"key":"yuri.kanivetsky@gmail.com","avatar":"https://gravatar.com/avatar/e4d91cf41e555a0c340222a1898c6320f51ad5ab2f9638282cc2412abb450648?d=mp&s=160"},"body":"Hi,\n\nFrom what I can see w/o `-3` `git am` follows the `patch`'es behavior.\nAnd the `patch`'es behavior is if there are lines in a patch that\ndoesn't match the lines in the source file, it fails. For example, a\nsource file:\n\n11\n2\n3\n\nA patch:\n\n 1\n 2\n-3\n+33\n\nBut `git am -3` will apply such a patch. That is, `patch` sees that\nthe first line changed and that prevents it from applying the patch,\nbut `git am -3` decides that it's okay. Why is that?\n\nA script that reproduces the issue:\n\n    set -eux\n\n    mkdir a\n    (cd a\n    git init\n    echo '1\n    2\n    3' > a\n    git add a\n    git commit -m 1,2,3\n    sed -Ei 's/3/33/' a\n    git add a\n    git commit -m '3 -> 33'\n    git format-patch -1 HEAD)\n\n    mkdir b\n    (cd b\n    git init\n    echo '11\n    2\n    3' > a\n    git add a\n    git commit -m 11,2,3\n\n    git remote add a ../a\n    git fetch a\n\n    cat a\n    cat ../a/0001-3-33.patch\n    git --no-pager log --oneline --graph --all\n    git am \"$@\" ../a/0001-3-33.patch  # try it w/ and w/o -3\n    git --no-pager log --oneline --graph --all)\n\nA couple of links, just in case, which have more information and show\nwhere it comes from:\n\nhttps://stackoverflow.com/a/25847019/52499\nhttps://gist.github.com/x-yuri/9907d5b9cbf29e84d510902a776741df\nhttps://gist.github.com/x-yuri/57d08f6afb10a89856d6e6a62abe30d4\n\nRegards,\nYuri\n"},{"id":"458455","messageId":"CABPp-BEkEKQZR=1duxSS4AVv9u5tnPk5CaLCM_fQWPbAqfSMxw@mail.gmail.com","threadId":"58100","inReplyTo":"CAMhVC3Z92hBsK0FbE4E_LV1CSxjR1zmu+MO8=iwR02BKqnwgUA@mail.gmail.com","subject":"Re: Why `git am -3` apply patches that don't normally apply?","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2022-07-04T19:23:49Z","receivedAt":"2022-07-04T19:24:05Z","isPatch":false,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Sun, Jul 3, 2022 at 6:09 AM Yuri Kanivetsky\n<yuri.kanivetsky@gmail.com> wrote:\n>\n> Hi,\n>\n> From what I can see w/o `-3` `git am` follows the `patch`'es behavior.\n> And the `patch`'es behavior is if there are lines in a patch that\n> doesn't match the lines in the source file, it fails. For example, a\n> source file:\n>\n> 11\n> 2\n> 3\n>\n> A patch:\n>\n>  1\n>  2\n> -3\n> +33\n>\n> But `git am -3` will apply such a patch.\n\nWill apply the changes, but they might result in conflicts; it depends\non what you apply it to.\n\n> That is, `patch` sees that\n> the first line changed and that prevents it from applying the patch,\n> but `git am -3` decides that it's okay. Why is that?\n\nBecause `git am -3` is doing a three-way merge, as requested, where it\nis no longer using a patch with changes and a context region but\ninstead has three full files that it can three-way merge.  Let's dive\ninto your example to explain...\n\n> A script that reproduces the issue:\n>\n>     set -eux\n>\n>     mkdir a\n>     (cd a\n>     git init\n>     echo '1\n>     2\n>     3' > a\n>     git add a\n>     git commit -m 1,2,3\n>     sed -Ei 's/3/33/' a\n>     git add a\n>     git commit -m '3 -> 33'\n>     git format-patch -1 HEAD)\n\nSo you have a repository with two commits.  Also, format-patch puts\nreferences to the before-and-after blob hashes of the file 'a' into\nthe diff.\n\n>     mkdir b\n>     (cd b\n>     git init\n>     echo '11\n>     2\n>     3' > a\n>     git add a\n>     git commit -m 11,2,3\n>\n>     git remote add a ../a\n>     git fetch a\n\nSo 'b' is a repository with 3 commits; 1 that you added to it\ndirectly, and 2 that you fetched into it from your other repository.\n\nIf you had not done the fetch from 'a' into 'b', attempting to \"git am\n-3\" the patch you created earlier would fail.\n\n>     cat a\n>     cat ../a/0001-3-33.patch\n>     git --no-pager log --oneline --graph --all\n>     git am \"$@\" ../a/0001-3-33.patch  # try it w/ and w/o -3\n\nAs per the documentation of -3:\n\n        When the patch does not apply cleanly, fall back on\n        3-way merge if the patch records the identity of blobs\n        it is supposed to apply to and we have those blobs\n        available locally.\n\nformat-patch records the identity of the blobs, and your fetch made\nsure your 'b' repository has them.  So, it knows the base version of\nthe file has the following complete contents\n    1\n    2\n    3\nand the version from the patch has the following complete contents\n    1\n    2\n    33\nThe version in HEAD you are using in the three-way merge has the\nfollowing contents\n    11\n    2\n    3\nNote that here we are not dealing with limited context, but with the\nfull copies of the files.  Now, doing a three-way merge, we see that\nthe line with '2' is common in all three versions.  The first line was\nchanged from 1->11 on the HEAD side (and left alone on the other\nside), and the last line was changed from 3->33 on the other side\n(while being left alone on the HEAD side).  The three-way merge of\nthese is simply\n    11\n    2\n    33\n\nSo `git am -3` succeeds without conflicts for this case.\n"},{"id":"458490","messageId":"xmqqmtdnjut5.fsf@gitster.g","threadId":"58100","inReplyTo":"CABPp-BEkEKQZR=1duxSS4AVv9u5tnPk5CaLCM_fQWPbAqfSMxw@mail.gmail.com","subject":"Re: Why `git am -3` apply patches that don't normally apply?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-07-05T18:09:10Z","receivedAt":"2022-07-05T18:09:15Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Elijah Newren <newren@gmail.com> writes:\n\n> As per the documentation of -3:\n>\n>         When the patch does not apply cleanly, fall back on\n>         3-way merge if the patch records the identity of blobs\n>         it is supposed to apply to and we have those blobs\n>         available locally.\n\nI suspect that we would need to update this part, as the order of\n\"fall back\" was swapped sometime in the recent past (and we have\nfixed a few bugs that were introduced as fallouts).\n\nYour description on how -3 works when it does the three-way based on\nthe concrete example was very clear and easy to understand, by the\nway.\n\nThanks for writing it up.\n"},{"id":"458500","messageId":"CAMhVC3b+ByoxRn1o1WDvb3Rk07j_YQu9bd4w+STAgzNqkxK5ig@mail.gmail.com","threadId":"58100","inReplyTo":"xmqqmtdnjut5.fsf@gitster.g","subject":"Re: Why `git am -3` apply patches that don't normally apply?","fromName":"Yuri Kanivetsky","fromEmail":"yuri.kanivetsky@gmail.com","sentAt":"2022-07-06T00:19:00Z","receivedAt":"2022-07-06T00:19:15Z","isPatch":false,"sender":{"key":"yuri.kanivetsky@gmail.com","avatar":"https://gravatar.com/avatar/e4d91cf41e555a0c340222a1898c6320f51ad5ab2f9638282cc2412abb450648?d=mp&s=160"},"body":"Yep, thanks for the detailed explanations. It let me improve my answer\non Stack Overflow:\n\nhttps://stackoverflow.com/questions/25846189/git-am-error-patch-does-not-apply/72797965#72797965\n\nAlthough... it'll unlikely receive a lot of views :( But whatever, it\ncan't be helped.\n\nRegards,\nYuri\n\nOn Tue, Jul 5, 2022 at 9:09 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Elijah Newren <newren@gmail.com> writes:\n>\n> > As per the documentation of -3:\n> >\n> >         When the patch does not apply cleanly, fall back on\n> >         3-way merge if the patch records the identity of blobs\n> >         it is supposed to apply to and we have those blobs\n> >         available locally.\n>\n> I suspect that we would need to update this part, as the order of\n> \"fall back\" was swapped sometime in the recent past (and we have\n> fixed a few bugs that were introduced as fallouts).\n>\n> Your description on how -3 works when it does the three-way based on\n> the concrete example was very clear and easy to understand, by the\n> way.\n>\n> Thanks for writing it up.\n"}]}