{"thread":{"id":"55184","subject":"git format-patch lost the last part when branch merge","startedAt":"2021-02-22T13:19:12Z","lastAt":"2021-02-24T04:51:25Z","messageCount":10,"participants":["Wang Yugui","Jeff King","Junio C Hamano","Elijah Newren"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"417467","messageId":"20210222211621.0C5D.409509F4@e16-tech.com","threadId":"55184","inReplyTo":null,"subject":"git format-patch lost the last part when branch merge","fromName":"Wang Yugui","fromEmail":"wangyugui@e16-tech.com","sentAt":"2021-02-22T13:16:21Z","receivedAt":"2021-02-22T13:19:12Z","isPatch":false,"sender":{"key":"wangyugui@e16-tech.com","avatar":null},"body":"Hi,\n\ngit format-patch lost the last part when branch merge\n\nHere is an example.\n\nhttps://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git\nMerge tag 'for-5.12/block-2021-02-17' of git://git.kernel.dk/linux-block\n\n1, from the web interface,\nhttps://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/fs/btrfs?id=582cd91f69de8e44857cb610ebca661dac8656b7\n\nthe last part 'diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c' can be confirmed.\n\n2, but from ' commit | 582cd91f69de8e44857cb610ebca661dac8656b7 (patch)' of this web page,\nthe last part 'diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c' is not in the patch file.\n\n3, git format-patch 4f016a316f22.. fs/btrfs/ will not output 'diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c' too.\n\nBest Regards\n\n\n[System Info]\ngit version:\ngit version 2.30.1 and 2.27.0\ncpu: x86_64\nno commit associated with this build\nsizeof-long: 8\nsizeof-size_t: 8\nshell-path: /bin/sh\nuname: Linux 5.10.17-3.el7.x86_64 #1 SMP Mon Feb 22 10:43:13 CST 2021 x86_64\ncompiler info: gnuc: 4.8\nlibc info: glibc: 2.17\n$SHELL (typically, interactive shell): /bin/bash\n\n\n[Enabled Hooks]\nNone\n\n\nBest Regards\n王玉贵\n2021/02/22\n\n--------------------------------------\n北京京垓科技有限公司\n王玉贵\twangyugui@e16-tech.com\n电话：+86-136-71123776\n\n"},{"id":"417499","messageId":"YDQ27qbbblPfLCpU@coredump.intra.peff.net","threadId":"55184","inReplyTo":"20210222211621.0C5D.409509F4@e16-tech.com","subject":"Re: git format-patch lost the last part when branch merge","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2021-02-22T22:57:50Z","receivedAt":"2021-02-22T22:58:42Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Feb 22, 2021 at 09:16:21PM +0800, Wang Yugui wrote:\n\n> git format-patch lost the last part when branch merge\n> \n> Here is an example.\n> \n> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git\n> Merge tag 'for-5.12/block-2021-02-17' of git://git.kernel.dk/linux-block\n> \n> 1, from the web interface,\n> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/fs/btrfs?id=582cd91f69de8e44857cb610ebca661dac8656b7\n> \n> the last part 'diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c' can be confirmed.\n> \n> 2, but from ' commit | 582cd91f69de8e44857cb610ebca661dac8656b7 (patch)' of this web page,\n> the last part 'diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c' is not in the patch file.\n> \n> 3, git format-patch 4f016a316f22.. fs/btrfs/ will not output 'diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c' too.\n\nThis is expected. Format-patch omits merge commits entirely, as they\ncan't be formatted as a simple diff that can be applied.\n\nThere are lots of ways to look at the diff of a merge. By default, `git\nshow` will show a combined diff, which omits hunks where one side was\ntaken verbatim, but otherwise shows what each side did.\n\nThe diff shown in the link above is a diff against the first-parent\n(which you can also get locally with `git show --first-parent 582cd91`).\nOne _could_ apply that diff onto the first parent to achieve the same\ntree as the merge plus all of the commits that got merged in. But it\nwouldn't make any sense to apply that (aside from conflict resolution,\nit would be redundant with all of the commits that format-patch just\noutput!).\n\nYou could imagine ways for format-patch to represent the conflict\nresolution done in a merge, but it's not quite trivial, and nobody has\ndone it yet.\n\nDepending on why you're using format-patch, the solution may be one of:\n\n  - use \"git log --cc\" instead, which shows the merges using combined\n    diffs\n\n  - use \"git bundle\" instead, which reproduces the whole history graph,\n    including merges (though obviously you cannot then re-apply the\n    commits onto a different history)\n\n-Peff\n"},{"id":"417501","messageId":"YDQ5YIeXGiR5nvLH@coredump.intra.peff.net","threadId":"55184","inReplyTo":"YDQ27qbbblPfLCpU@coredump.intra.peff.net","subject":"[PATCH] docs/format-patch: mention handling of merges","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2021-02-22T23:08:16Z","receivedAt":"2021-02-22T23:08:59Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Feb 22, 2021 at 05:57:50PM -0500, Jeff King wrote:\n\n> This is expected. Format-patch omits merge commits entirely, as they\n> can't be formatted as a simple diff that can be applied.\n\nWe don't seem to advertise this very well in the documentation.\n\nI think we should at least do something like the patch below. I do have\na dream that one day we'll be able to represent conflict resolutions\nover email, but we're not there yet.\n\nLikewise, it might be reasonable format-patch to issue a warning() when\nit is ignoring a merge. Or maybe some people would find that annoying\n(e.g., because they don't care about back-merges from upstream that\nhappened during the development of a topic).\n\nBut I think this documentation change is easy and hopefully\nuncontroversial.\n\n-- >8 --\nSubject: [PATCH] docs/format-patch: mention handling of merges\n\nFormat-patch doesn't have a way to format merges in a way that can be\napplied by git-am (or any other tool), and so it just omits them.\nHowever, this may be a surprising implication for users who are not well\nversed in how the tool works. Let's add a note to the documentation\nmaking this more clear.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\n Documentation/git-format-patch.txt | 9 ++++++++-\n 1 file changed, 8 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt\nindex 3e49bf2210..33649098ce 100644\n--- a/Documentation/git-format-patch.txt\n+++ b/Documentation/git-format-patch.txt\n@@ -36,7 +36,7 @@ SYNOPSIS\n DESCRIPTION\n -----------\n \n-Prepare each commit with its patch in\n+Prepare each non-merge commit with its patch in\n one file per commit, formatted to resemble UNIX mailbox format.\n The output of this command is convenient for e-mail submission or\n for use with 'git am'.\n@@ -718,6 +718,13 @@ use it only when you know the recipient uses Git to apply your patch.\n $ git format-patch -3\n ------------\n \n+CAVEATS\n+-------\n+\n+Note that `format-patch` cannot represent commits with more than one\n+parent (i.e., merges) and will silently omit them entirely from its\n+output, even if they are part of the requested range.\n+\n SEE ALSO\n --------\n linkgit:git-am[1], linkgit:git-send-email[1]\n-- \n2.30.1.1033.gd525307ce1\n\n"},{"id":"417502","messageId":"xmqqzgzv65y6.fsf@gitster.g","threadId":"55184","inReplyTo":"YDQ27qbbblPfLCpU@coredump.intra.peff.net","subject":"Re: git format-patch lost the last part when branch merge","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-02-22T23:25:21Z","receivedAt":"2021-02-22T23:26:06Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> This is expected. Format-patch omits merge commits entirely, as they\n> can't be formatted as a simple diff that can be applied.\n>\n> There are lots of ways to look at the diff of a merge. By default, `git\n> show` will show a combined diff, which omits hunks where one side was\n> taken verbatim, but otherwise shows what each side did.\n>\n> The diff shown in the link above is a diff against the first-parent\n> (which you can also get locally with `git show --first-parent 582cd91`).\n> One _could_ apply that diff onto the first parent to achieve the same\n> tree as the merge plus all of the commits that got merged in. But it\n> wouldn't make any sense to apply that (aside from conflict resolution,\n> it would be redundant with all of the commits that format-patch just\n> output!).\n\nYes, a first-parent diff is something you could call \"a simple diff\nthat can be applied to represent a merge\", and it is consistent with\nthe expectations of those who are used to do a squash (pseudo-)merge.\n\nI agree with you that it does not make sense to apply such a patch\nas a patch, of course.  In addition to be redundant, it would be an\nequivalent of doing a squash (psuedo-)merge, and loses the \"up to\nthis point the side branch has been merged, so future merges won't\nhave to look beyond this point in the past\" (sort of going back to\nthe prehistoric subversion days that did not keep track of which\nchanges have been merged).\n"},{"id":"417503","messageId":"xmqqv9aj65na.fsf@gitster.g","threadId":"55184","inReplyTo":"YDQ5YIeXGiR5nvLH@coredump.intra.peff.net","subject":"Re: [PATCH] docs/format-patch: mention handling of merges","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-02-22T23:31:53Z","receivedAt":"2021-02-22T23:32:46Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> Subject: [PATCH] docs/format-patch: mention handling of merges\n>\n> Format-patch doesn't have a way to format merges in a way that can be\n> applied by git-am (or any other tool), and so it just omits them.\n> However, this may be a surprising implication for users who are not well\n> versed in how the tool works. Let's add a note to the documentation\n> making this more clear.\n> ...\n> +CAVEATS\n> +-------\n> +\n> +Note that `format-patch` cannot represent commits with more than one\n> +parent (i.e., merges) and will silently omit them entirely from its\n> +output, even if they are part of the requested range.\n\n\nI think \"cannot represent\" is a little bit misleading, unless we\nexpect the readers already know what we are trying to say (in which\ncase there is no point in documenting this).  Perhaps something like\nthis might clarify a bit, though.\n\n    Note that `format-patch` omits merge commits from the output,\n    because it is impossible to turn a merge commit into a simple\n    \"patch\" in such a way that allows receiving end to reproduce the\n    same merge commit.\n\n"},{"id":"417506","messageId":"YDRA6RJdnFne2EBw@coredump.intra.peff.net","threadId":"55184","inReplyTo":"xmqqv9aj65na.fsf@gitster.g","subject":"Re: [PATCH] docs/format-patch: mention handling of merges","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2021-02-22T23:40:25Z","receivedAt":"2021-02-22T23:41:08Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Feb 22, 2021 at 03:31:53PM -0800, Junio C Hamano wrote:\n\n> Jeff King <peff@peff.net> writes:\n> \n> > Subject: [PATCH] docs/format-patch: mention handling of merges\n> >\n> > Format-patch doesn't have a way to format merges in a way that can be\n> > applied by git-am (or any other tool), and so it just omits them.\n> > However, this may be a surprising implication for users who are not well\n> > versed in how the tool works. Let's add a note to the documentation\n> > making this more clear.\n> > ...\n> > +CAVEATS\n> > +-------\n> > +\n> > +Note that `format-patch` cannot represent commits with more than one\n> > +parent (i.e., merges) and will silently omit them entirely from its\n> > +output, even if they are part of the requested range.\n> \n> \n> I think \"cannot represent\" is a little bit misleading, unless we\n> expect the readers already know what we are trying to say (in which\n> case there is no point in documenting this).  Perhaps something like\n> this might clarify a bit, though.\n> \n>     Note that `format-patch` omits merge commits from the output,\n>     because it is impossible to turn a merge commit into a simple\n>     \"patch\" in such a way that allows receiving end to reproduce the\n>     same merge commit.\n\nThat seems worse to me, because \"it is impossible\" implies that this\ncan never be changed. But I don't think that's true. We might one day\noutput something useful for merges.\n\nI think one could argue that any merge information (including conflict\nresolution) works against the root notion of format-patch, which is a\nset of changes that can be applied on a range of basesa. But even that I\nwould be hesitant to commit to (since --base exists now). And certainly\nit's more subtlety than I'd want to get in to for this note. :)\n\nI almost softened it to \"cannot yet represent\". Does that read better to\nyour (or worse)? Likewise, I considered adding a note at the end along\nthe lines of \"this may change in the future\", though I suspect we'd only\ndo so in combination with a command-line option.\n\n-Peff\n"},{"id":"417518","messageId":"xmqqblcb60fz.fsf@gitster.g","threadId":"55184","inReplyTo":"YDRA6RJdnFne2EBw@coredump.intra.peff.net","subject":"Re: [PATCH] docs/format-patch: mention handling of merges","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-02-23T01:24:16Z","receivedAt":"2021-02-23T01:26:11Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> That seems worse to me, because \"it is impossible\" implies that this\n> can never be changed. But I don't think that's true. We might one day\n> output something useful for merges.\n\nFair enough.  You are more optimistic than I am ;-)\n\n> I think one could argue that any merge information (including conflict\n> resolution) works against the root notion of format-patch, which is a\n> set of changes that can be applied on a range of basesa.\n\nThat's true and it was the primary motive for omiting merges.\n\n> But even that I\n> would be hesitant to commit to (since --base exists now).\n\nI am not quite sure what --base has to throw into the equation.  The\ninformation --base gives is often useful when I want to learn where\nthe patches were taken from, but that does not restrict where the\npatches are actually applied to in any meaningful way (iow, \"on a\nrange of bases\" part is not affected).\n\n"},{"id":"417520","messageId":"YDRe7AAOnHPmAhp4@coredump.intra.peff.net","threadId":"55184","inReplyTo":"xmqqblcb60fz.fsf@gitster.g","subject":"Re: [PATCH] docs/format-patch: mention handling of merges","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2021-02-23T01:48:28Z","receivedAt":"2021-02-23T01:49:35Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Feb 22, 2021 at 05:24:16PM -0800, Junio C Hamano wrote:\n\n> > I think one could argue that any merge information (including conflict\n> > resolution) works against the root notion of format-patch, which is a\n> > set of changes that can be applied on a range of basesa.\n> \n> That's true and it was the primary motive for omiting merges.\n> \n> > But even that I\n> > would be hesitant to commit to (since --base exists now).\n> \n> I am not quite sure what --base has to throw into the equation.  The\n> information --base gives is often useful when I want to learn where\n> the patches were taken from, but that does not restrict where the\n> patches are actually applied to in any meaningful way (iow, \"on a\n> range of bases\" part is not affected).\n\nWhat I meant is that without \"--base\", telling somebody \"here is the\nmerge you should replay on top of these other patches\" is virtually\nmeaningless. You cannot know what the merge base would be! So you might\nbe merging in other random crap, and you might or might not see the same\nconflicts.\n\nBut in a world with --base, I can imagine some people recreating whole\nsequences of the history graph by using \"--base\" along with some (to be\ninvented) format for representing a merge via email. That mode would\ncertainly not be the default, but at least at that point it is\nconceivably useful. Sort of like a bundle, but more human-readable (it\nwould also need committer info to recreate the commit ids perfectly, of\ncourse).\n\nAll of which meant only to argue that \"it is not possible or not useful\nto represent a merge in an email\" is something that could change in the\nfuture. :)\n\n-Peff\n"},{"id":"417656","messageId":"CABPp-BFa3CnOHMg4t99xMHWif8kMZJFcmHtLSNxZgAPaw1Cd=Q@mail.gmail.com","threadId":"55184","inReplyTo":"YDQ27qbbblPfLCpU@coredump.intra.peff.net","subject":"Re: git format-patch lost the last part when branch merge","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2021-02-24T04:24:24Z","receivedAt":"2021-02-24T04:29:56Z","isPatch":false,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Mon, Feb 22, 2021 at 3:03 PM Jeff King <peff@peff.net> wrote:\n[...snip...]\n>\n> There are lots of ways to look at the diff of a merge. By default, `git\n> show` will show a combined diff, which omits hunks where one side was\n> taken verbatim, but otherwise shows what each side did.\n>\n> The diff shown in the link above is a diff against the first-parent\n> (which you can also get locally with `git show --first-parent 582cd91`).\n> One _could_ apply that diff onto the first parent to achieve the same\n> tree as the merge plus all of the commits that got merged in. But it\n> wouldn't make any sense to apply that (aside from conflict resolution,\n> it would be redundant with all of the commits that format-patch just\n> output!).\n>\n> You could imagine ways for format-patch to represent the conflict\n> resolution done in a merge, but it's not quite trivial, and nobody has\n> done it yet.\n\nAre you referring to something like this (in the git.git repository)?\n\n$ git show --oneline --remerge-diff 42342b3ee6\n42342b3ee6 Merge branch 'ab/mailmap'\ndiff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh\nindex 1bce961e07..6fb18a34b0 100755\n--- a/t/t4203-mailmap.sh\n+++ b/t/t4203-mailmap.sh\n@@ -257,16 +257,8 @@ test_expect_success 'No mailmap files, but configured' '\n\n test_expect_success 'setup mailmap blob tests' '\n        git checkout -b map &&\n-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 60ecad090d (Merge branch 'ps/fetch-atomic')\n        test_when_finished \"git checkout main\" &&\n-       cat >just-bugs <<- EOF &&\n-|||||||||||||||||||||||||||||||| 72c4083ddf\n-       test_when_finished \"git checkout master\" &&\n-       cat >just-bugs <<- EOF &&\n-================================\n-       test_when_finished \"git checkout master\" &&\n        cat >just-bugs <<-\\EOF &&\n->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 4e168333a8 (shortlog: remove\nunused(?) \"repo-abbrev\" feature)\n        Blob Guy <bugs@company.xx>\n        EOF\n        cat >both <<-EOF &&\n\n\nI agree that representing the conflict done in a merge is more\ndifficult than it sounds, but if you mean what I think you mean then I\ndisagree with the \"nobody has done it yet\" half of your statement.\n:-)\n\nThat said, I haven't attempted to tie this into format-patch in any\nway, and have absolutely no plans to.  (And --remerge-diff hasn't been\nsubmitted upstream, because it depends on ort, and that still needs\nreviews...)\n"},{"id":"417660","messageId":"YDXbIk5TLrHWQhwv@coredump.intra.peff.net","threadId":"55184","inReplyTo":"CABPp-BFa3CnOHMg4t99xMHWif8kMZJFcmHtLSNxZgAPaw1Cd=Q@mail.gmail.com","subject":"Re: git format-patch lost the last part when branch merge","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2021-02-24T04:50:42Z","receivedAt":"2021-02-24T04:51:25Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, Feb 23, 2021 at 08:24:24PM -0800, Elijah Newren wrote:\n\n> > You could imagine ways for format-patch to represent the conflict\n> > resolution done in a merge, but it's not quite trivial, and nobody has\n> > done it yet.\n> \n> Are you referring to something like this (in the git.git repository)?\n> \n> $ git show --oneline --remerge-diff 42342b3ee6\n> 42342b3ee6 Merge branch 'ab/mailmap'\n> diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh\n> index 1bce961e07..6fb18a34b0 100755\n> --- a/t/t4203-mailmap.sh\n> +++ b/t/t4203-mailmap.sh\n> @@ -257,16 +257,8 @@ test_expect_success 'No mailmap files, but configured' '\n> \n>  test_expect_success 'setup mailmap blob tests' '\n>         git checkout -b map &&\n> -<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 60ecad090d (Merge branch 'ps/fetch-atomic')\n>         test_when_finished \"git checkout main\" &&\n> -       cat >just-bugs <<- EOF &&\n> -|||||||||||||||||||||||||||||||| 72c4083ddf\n> -       test_when_finished \"git checkout master\" &&\n> -       cat >just-bugs <<- EOF &&\n> -================================\n> -       test_when_finished \"git checkout master\" &&\n>         cat >just-bugs <<-\\EOF &&\n> ->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 4e168333a8 (shortlog: remove\n> unused(?) \"repo-abbrev\" feature)\n>         Blob Guy <bugs@company.xx>\n>         EOF\n>         cat >both <<-EOF &&\n> \n> \n> I agree that representing the conflict done in a merge is more\n> difficult than it sounds, but if you mean what I think you mean then I\n> disagree with the \"nobody has done it yet\" half of your statement.\n> :-)\n> \n> That said, I haven't attempted to tie this into format-patch in any\n> way, and have absolutely no plans to.  (And --remerge-diff hasn't been\n> submitted upstream, because it depends on ort, and that still needs\n> reviews...)\n\nI certainly was thinking of remerge-diff when I was writing all of that,\nbut didn't want to get too far into the details. I think it's an\nabsolutely wonderful way of showing off conflict resolution, and I'm\nexcited to see it as a feature in Git. But:\n\n  - as you note, it isn't a public feature yet ;)\n\n  - while format-patch will learn about it because it knows all of the\n    diff formats, the fundamental point of format-patch is to produce\n    output that can be applied with git-am. So we'd only be halfway\n    there.\n\n  - it does still get weird specifying a merge at all as part of a\n    series. Merging _what_ exactly? The topic branch made of the patches\n    that were just sent?  A back-merge from some other commit on master\n    into the topic branch? And if the latter, wouldn't that depend\n    heavily on the base commit that the patches are applied on top of?\n\nSo I left it as \"you could imagine\" and \"it's not quite trivial\". ;)\n\n-Peff\n"}]}