{"thread":{"id":"28881","subject":"git-apply that handles rejects like merge conflicts","startedAt":"2011-11-07T22:10:48Z","lastAt":"2011-11-08T21:00:45Z","messageCount":10,"participants":["Ori Avtalion","Jeff King","Junio C Hamano","Bert Wesarg"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"179090","messageId":"4EB85768.1060508@avtalion.name","threadId":"28881","inReplyTo":null,"subject":"git-apply that handles rejects like merge conflicts","fromName":"Ori Avtalion","fromEmail":"ori@avtalion.name","sentAt":"2011-11-07T22:10:48Z","receivedAt":"2011-11-07T22:10:48Z","isPatch":false,"sender":{"key":"ori@avtalion.name","avatar":"https://avatars.githubusercontent.com/u/28355?v=4"},"body":"Hey,\n\nI'm trying to get git-apply to apply patches, and let me handle the\nconflicts in a way I'm comfortable with -- by staging the \"successful\"\nhunks and leaving conflict markers in the working tree.\n\nWith the available flags, I seem to only be able to have successful\nhunks in the index, and rejected ones in patch-like .rej files.\n\nIs there a way to accomplish this? If not, does anyone think it's a good\nidea?\n\n-Ori\n"},{"id":"179094","messageId":"20111107225508.GB28188@sigill.intra.peff.net","threadId":"28881","inReplyTo":"4EB85768.1060508@avtalion.name","subject":"Re: git-apply that handles rejects like merge conflicts","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-11-07T22:55:08Z","receivedAt":"2011-11-07T22:55:08Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, Nov 08, 2011 at 12:10:48AM +0200, Ori Avtalion wrote:\n\n> I'm trying to get git-apply to apply patches, and let me handle the\n> conflicts in a way I'm comfortable with -- by staging the \"successful\"\n> hunks and leaving conflict markers in the working tree.\n> \n> With the available flags, I seem to only be able to have successful\n> hunks in the index, and rejected ones in patch-like .rej files.\n> \n> Is there a way to accomplish this? If not, does anyone think it's a good\n> idea?\n\nNo, I don't think there's a way to do it now. I do find the conflict\nmarkers the easiest way to mark something up. But most of my \"git apply\"\nuse is through \"git am\", which knows the trick of falling back to a\n3-way merge (see fall_back_3way in git-am.sh).\n\nIf it's an actual git diff, the same 3-way trick will yield good\nresults, and it would be nice if it were easier to do that trick without\ncalling \"git am\". But if it's not a git diff (i.e., missing the original\nblob information), then you won't be able to do that.\n\nIn the general case, you can't represent all failed hunks with conflict\nmarkers, can you? I'm thinking something where we couldn't find any\nrelevant context. You know the lines from the original patch from the\nhunk header, so you can drop the failed content from the patch in the\nright spot. But how do you know how big a conflict marker to make for\nthe \"current\" side? The same number of lines as were in the hunk?\nI think you'd end up with confusing conflict markers.\n\n-Peff\n"},{"id":"179096","messageId":"4EB86741.7040809@avtalion.name","threadId":"28881","inReplyTo":"20111107225508.GB28188@sigill.intra.peff.net","subject":"Re: git-apply that handles rejects like merge conflicts","fromName":"Ori Avtalion","fromEmail":"ori@avtalion.name","sentAt":"2011-11-07T23:18:25Z","receivedAt":"2011-11-07T23:18:25Z","isPatch":false,"sender":{"key":"ori@avtalion.name","avatar":"https://avatars.githubusercontent.com/u/28355?v=4"},"body":"On 11/08/2011 12:55 AM, Jeff King wrote:\n> If it's an actual git diff, the same 3-way trick will yield good\n> results, and it would be nice if it were easier to do that trick without\n> calling \"git am\". But if it's not a git diff (i.e., missing the original\n> blob information), then you won't be able to do that.\n\nI'm dealing with two codebases that have branched in the past, before\nany VCS was used, and now I'm tracking both separately with git. I'm\ntrying to  apply changes from one to the other with format-patch and\ngit-am/apply. So yeah, no blob info.\n\n> In the general case, you can't represent all failed hunks with conflict\n> markers, can you? I'm thinking something where we couldn't find any\n> relevant context. You know the lines from the original patch from the\n> hunk header, so you can drop the failed content from the patch in the\n> right spot. But how do you know how big a conflict marker to make for\n> the \"current\" side? The same number of lines as were in the hunk?\n> I think you'd end up with confusing conflict markers.\n\nPersonally, I wouldn't object to having both \"computable\" conflicts, and\nthe .rej files for hunks that lack context, but I see how that would be\nvery confusing. :)\n\n-Ori\n"},{"id":"179098","messageId":"7v4nyf1opf.fsf@alter.siamese.dyndns.org","threadId":"28881","inReplyTo":"20111107225508.GB28188@sigill.intra.peff.net","subject":"Re: git-apply that handles rejects like merge conflicts","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-07T23:45:48Z","receivedAt":"2011-11-07T23:45:48Z","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> In the general case, you can't represent all failed hunks with conflict\n> markers, can you?\n\nConflict markers come from the use of a 3-way merge, and if you were to do\na 3-way merge, by definition, you would need some way to tell where the\npreimage of the patch and the target tree you are attempting to apply the\npatch forked from. That's done by fall-back-3way in \"am -3\".\n\nYou _could_ lift that logic out of \"am -3\", but I do not think it is worth\nthe effort to do so (IOW, I do not see a reason to avoid \"am -3\").\n\nIf you do not want to create a commit for whatever reason, then you can\n\"reset --soft\" back.\n"},{"id":"179123","messageId":"20111108054643.GC29643@sigill.intra.peff.net","threadId":"28881","inReplyTo":"7v4nyf1opf.fsf@alter.siamese.dyndns.org","subject":"Re: git-apply that handles rejects like merge conflicts","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-11-08T05:46:43Z","receivedAt":"2011-11-08T05:46:43Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Nov 07, 2011 at 03:45:48PM -0800, Junio C Hamano wrote:\n\n> Jeff King <peff@peff.net> writes:\n> \n> > In the general case, you can't represent all failed hunks with conflict\n> > markers, can you?\n> \n> Conflict markers come from the use of a 3-way merge, and if you were to do\n> a 3-way merge, by definition, you would need some way to tell where the\n> preimage of the patch and the target tree you are attempting to apply the\n> patch forked from. That's done by fall-back-3way in \"am -3\".\n> \n> You _could_ lift that logic out of \"am -3\", but I do not think it is worth\n> the effort to do so (IOW, I do not see a reason to avoid \"am -3\").\n\nI think it would purely be \"I have a patch produced by git diff, not by\ngit format-patch\". If you want to use \"am -3\", you would have to dress\nup your patch with mail headers.\n\nIn practice, this doesn't come up much for me. I think I was using \"git\ndiff >patch\" as a poor-man's stash (and I did just stick some fake\nheaders in, and \"git reset HEAD^\" afterwards). But maybe other workflows\ndeal with this more.\n\nBut I think there are two questions:\n\n  1. Should am's 3-way fallback be made more easily available to users\n     of regular \"apply\"?\n\n  2. Short of doing a 3-way merge, are there better ways to represent\n     failed hunks in the patch target itself, rather than saving \".rej\"\n     files?\n\nI'm actually not sure which one Ori was asking about.\n\n-Peff\n"},{"id":"179125","messageId":"7vd3d3ywai.fsf@alter.siamese.dyndns.org","threadId":"28881","inReplyTo":"20111108054643.GC29643@sigill.intra.peff.net","subject":"Re: git-apply that handles rejects like merge conflicts","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-11-08T06:15:33Z","receivedAt":"2011-11-08T06:15:33Z","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> But I think there are two questions:\n>\n>   1. Should am's 3-way fallback be made more easily available to users\n>      of regular \"apply\"?\n>\n>   2. Short of doing a 3-way merge, are there better ways to represent\n>      failed hunks in the patch target itself, rather than saving \".rej\"\n>      files?\n>\n> I'm actually not sure which one Ori was asking about.\n\nMe neither, but if I have to guess it would be the former. If there were a\nsolution better than \".rej\" in 2-way context, surely \"patch\" would have\nimplemented it 10 years before we started ;-).\n"},{"id":"179128","messageId":"CAKPyHN1cqG9-g1Q4iGbUOtfiXLc6EPcFH2cWNCep3af4cTdzSg@mail.gmail.com","threadId":"28881","inReplyTo":"20111107225508.GB28188@sigill.intra.peff.net","subject":"Re: git-apply that handles rejects like merge conflicts","fromName":"Bert Wesarg","fromEmail":"bert.wesarg@googlemail.com","sentAt":"2011-11-08T08:52:26Z","receivedAt":"2011-11-08T08:52:26Z","isPatch":false,"sender":{"key":"bert.wesarg@googlemail.com","avatar":"https://avatars.githubusercontent.com/u/111934?v=4"},"body":"On Mon, Nov 7, 2011 at 23:55, Jeff King <peff@peff.net> wrote:\n> In the general case, you can't represent all failed hunks with conflict\n> markers, can you? I'm thinking something where we couldn't find any\n> relevant context. You know the lines from the original patch from the\n> hunk header, so you can drop the failed content from the patch in the\n> right spot. But how do you know how big a conflict marker to make for\n> the \"current\" side? The same number of lines as were in the hunk?\n> I think you'd end up with confusing conflict markers.\n\nGNU patch can produce conflict markers with the --merge option.\n\nBert\n\n>\n> -Peff\n"},{"id":"179142","messageId":"20111108161014.GA14049@sigill.intra.peff.net","threadId":"28881","inReplyTo":"CAKPyHN1cqG9-g1Q4iGbUOtfiXLc6EPcFH2cWNCep3af4cTdzSg@mail.gmail.com","subject":"Re: git-apply that handles rejects like merge conflicts","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-11-08T16:10:15Z","receivedAt":"2011-11-08T16:10:15Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, Nov 08, 2011 at 09:52:26AM +0100, Bert Wesarg wrote:\n\n> On Mon, Nov 7, 2011 at 23:55, Jeff King <peff@peff.net> wrote:\n> > In the general case, you can't represent all failed hunks with conflict\n> > markers, can you? I'm thinking something where we couldn't find any\n> > relevant context. You know the lines from the original patch from the\n> > hunk header, so you can drop the failed content from the patch in the\n> > right spot. But how do you know how big a conflict marker to make for\n> > the \"current\" side? The same number of lines as were in the hunk?\n> > I think you'd end up with confusing conflict markers.\n> \n> GNU patch can produce conflict markers with the --merge option.\n\nHmm. Yeah, it does work, but as I feared, it can produce pretty awful\nconflicts. Try this fairly straightforward setup (3 lines changed in the\nmiddle of a file):\n\n  git init &&\n  seq 1 10 >file && git add file && git commit -m base &&\n  sed -i '3,5s/$/ master/' file && git commit -a -m master &&\n  git checkout -b other HEAD^ &&\n  sed -i '3,5s/$/ other/' file && git commit -a -m other\n\nYou can see what a real merge looks like:\n\n  git merge master &&\n  $EDITOR file\n\nwhich is:\n\n  1\n  2\n  <<<<<<< HEAD\n  3 other\n  4 other\n  5 other\n  =======\n  3 master\n  4 master\n  5 master\n  >>>>>>> master\n  6\n  7\n  8\n  9\n  10\n\nIf you use \"patch --merge\", you get the same thing. Which is good. But\nnow try it with 10 lines changed out of 100:\n\n  rm -rf .git\n  git init &&\n  seq 1 100 >file && git add file && git commit -m base &&\n  sed -i '50,60s/$/ master/' file && git commit -a -m master &&\n  git checkout -b other HEAD^ &&\n  sed -i '50,60s/$/ other/' file && git commit -a -m other\n\nDoing a merge will get you the same sensible results. But \"patch\n--merge\" produces:\n\n ...\n 45\n 46\n <<<<<<<\n =======\n 47\n 48\n 49\n 50 master\n ...\n 60 master\n 61\n 62\n 63\n >>>>>>>\n 47\n 48\n 49\n 50 other\n 51 other\n 52 other\n 53 other\n ...\n\nwhich is not that helpful. Interestingly, I think it _should_ be able to\ndo the same thing here as it did on the 3-line case. So I'm not sure\nwhy it doesn't.\n\nBut there are even more complex cases, like say \"other\" had added new\nlines of new content at the beginning of the file, and messed up the\ncontext lines that the patch was using. So I think in the general case,\nyou will end up with patches like the latter one. Just shoving the patch\nhunk into the file with an empty preimage section. And that can even\nstill be useful, but you are relying on line counts then. If they're\noff, it's going ot be quite confusing.\n\n-Peff\n"},{"id":"179159","messageId":"4EB9962B.8060809@avtalion.name","threadId":"28881","inReplyTo":"20111108054643.GC29643@sigill.intra.peff.net","subject":"Re: git-apply that handles rejects like merge conflicts","fromName":"Ori Avtalion","fromEmail":"ori@avtalion.name","sentAt":"2011-11-08T20:50:51Z","receivedAt":"2011-11-08T20:50:51Z","isPatch":false,"sender":{"key":"ori@avtalion.name","avatar":"https://avatars.githubusercontent.com/u/28355?v=4"},"body":"On 11/08/2011 07:46 AM, Jeff King wrote:\n> On Mon, Nov 07, 2011 at 03:45:48PM -0800, Junio C Hamano wrote:\n> But I think there are two questions:\n> \n[ snip ]\n> \n> I'm actually not sure which one Ori was asking about.\n> \n\nI'm actually interested in both :)\n\nHere's a copy of the description of my problem from another reply:\n\n> I'm dealing with two codebases that have branched in the past, before\n> any VCS was used, and now I'm tracking both separately with git. I'm\n> trying to  apply changes from one to the other with format-patch and\n> git-am/apply.\n\nIn answer to your first question\n>   1. Should am's 3-way fallback be made more easily available to users\n>      of regular \"apply\"?\n\ngit-am is never part of this workflow as I'm trying to move patches\nbetween separate repositories with no shared root.\n\n<rant>\nAnd, personally, I don't think git-am is named correctly as the only\nuse-case I have for it is applying+committing single patches produced by\nformat-patch and sent as individual files over some medium which isn't\nmboxes (I'm not that old-school). I never understood why git-apply can't\ndo the commit and I have to instead use a tool with 'mail' in its name\n(Let's ignore the historical reasons) -- Shouldn't git-am be an\nmbox-reading wrapper around some more basic patch-applying tool?\n</rant>\n\n>>   2. Short of doing a 3-way merge, are there better ways to represent\n>>      failed hunks in the patch target itself, rather than saving \".rej\"\n>>      files?\n\nI really want this as .rej files feel very un-git-like. However, after\nunderstanding the problems raised in this thread, I'm a bit more\nrealistic :)\n\n-Ori\n"},{"id":"179161","messageId":"20111108210045.GA18666@sigill.intra.peff.net","threadId":"28881","inReplyTo":"4EB9962B.8060809@avtalion.name","subject":"Re: git-apply that handles rejects like merge conflicts","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-11-08T21:00:45Z","receivedAt":"2011-11-08T21:00:45Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, Nov 08, 2011 at 10:50:51PM +0200, Ori Avtalion wrote:\n\n> In answer to your first question\n> >   1. Should am's 3-way fallback be made more easily available to users\n> >      of regular \"apply\"?\n> \n> git-am is never part of this workflow as I'm trying to move patches\n> between separate repositories with no shared root.\n\nIsn't git-am the right tool for that? You format-patch out your commits\nin one repo, and then apply them in the other. No shared history is\nrequired; just the ability of the patches to actually be applied.\n\nIt _helps_ if you have the common base objects (the actual files, not\nthe commits), since the git diffs carry the pre- and post-image file\nsha1s, which is what allows us to do a real 3-way merge. In that case,\nit is just a matter of making the objects from the first repo available\nto git during the moment you are applying in the second repo. You could\ndo it by fetching the history of the first into a side-branch of the\nsecond, or even just by sharing object databases via the \"alternates\"\nmechanism.\n\n> <rant>\n> And, personally, I don't think git-am is named correctly as the only\n> use-case I have for it is applying+committing single patches produced by\n> format-patch and sent as individual files over some medium which isn't\n> mboxes (I'm not that old-school). I never understood why git-apply can't\n> do the commit and I have to instead use a tool with 'mail' in its name\n> (Let's ignore the historical reasons) -- Shouldn't git-am be an\n> mbox-reading wrapper around some more basic patch-applying tool?\n> </rant>\n\ngit-am _is_ an mbox-reading wrapper around some more basic\npatch-applying tool. That tool is \"git apply\". I think what you are\nmissing is that a single patch (or multiple patches) produced by\nformat-patch _is_ an mbox. There is nothing wrong with:\n\n  cd repo1 &&\n  git format-patch -1 --stdout >../my.patch &&\n  cd ../repo2 &&\n  git am ../my.patch\n\nThere is no standard for representing commit metadata in the diff\nformat. So git had to invent its own. It used rfc822 messages and\nmailboxes because it was simple and convenient, it mapped to what some\npeople were already doing, and it means we don't need a separate tool\nfor applying local commits versus ones that were emailed.\n\nSo the \"m\" is really for mbox, which happens to be git's format for\nstoring one or more commits, including metadata. If you just forget that\nit's associated with mail, then I think you will be happy. :)\n\n-Peff\n"}]}