{"thread":{"id":"27275","subject":"How to efficiently find where a patch applies?","startedAt":"2011-05-05T18:17:41Z","lastAt":"2011-05-05T20:17:18Z","messageCount":4,"participants":["Nathan W. Panike","Jeff King"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"167141","messageId":"20110505181741.GA27251@nwp-laptop","threadId":"27275","inReplyTo":null,"subject":"How to efficiently find where a patch applies?","fromName":"Nathan W. Panike","fromEmail":"nathan.panike@gmail.com","sentAt":"2011-05-05T18:17:41Z","receivedAt":"2011-05-05T18:17:41Z","isPatch":false,"sender":{"key":"nathan.panike@gmail.com","avatar":"https://avatars.githubusercontent.com/u/389447?v=4"},"body":"In the past couple weeks, I have had several occasions where a collaborator has\nsent a patch, which does not have information about where the patch forked from\nmaster.  I wrote the following scripts to try to discover where the patch\nshould be applied.  Is there a better way?\n\ncreate_awk.pl:\n----------------------->8------------------------------------------\n#! /usr/bin/env perl\nprint <<HEADER;\nBEGIN {\n\ti = 0\n}\nHEADER\n\nprint \"/\";\n\nmy $numseen=0;\nmy $nummatches = 0;\nwhile(<STDIN>){\n\tif(/^index ([0-9a-f]+)\\.\\..+$/){\n\t\t$hash = $1;\n\t} else {\n\t\tnext;\n\t}\n\tif($hash =~ /^0*$/) {\n\t\tnext;\n\t}\n\tprint \"|\" if($numseen > 0);\n\t$numseen = 1;\n\t++$nummatches;\n\tprint \"$hash\";\t\n}\nprint \"/{ i += 1; print \\$0}\\n\";\n\nprint <<FOOTER;\nEND {\n\tif( i == $nummatches) {\n\t\tprint \"FOUND IT\";\n\t\texit 1;\n\t}\n\tprint \"i =\",i;\n\texit 0;\n}\nFOOTER\n----------------------->8------------------------------------------\n\nTo find the place where the patch applies, I then would run something like\n\ngit rev-list --all | \\\nwhile read commit; do \\\n\tgit ls-tree -r $commit | \\\n\tawk \"$(perl ~/programs/git-hacks/create_awk.pl < <patch file>)\" > /dev/null || \\\n\techo $commit; \\\ndone\n\nNathan Panike\n"},{"id":"167170","messageId":"20110505195556.GA1770@sigill.intra.peff.net","threadId":"27275","inReplyTo":"20110505181741.GA27251@nwp-laptop","subject":"Re: How to efficiently find where a patch applies?","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-05-05T19:55:56Z","receivedAt":"2011-05-05T19:55:56Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, May 05, 2011 at 01:17:41PM -0500, Nathan W. Panike wrote:\n\n> In the past couple weeks, I have had several occasions where a collaborator has\n> sent a patch, which does not have information about where the patch forked from\n> master.  I wrote the following scripts to try to discover where the patch\n> should be applied.  Is there a better way?\n\nWhat you have is more or less the best way. As you probably realized,\nthere could be any number of commits that match the preimage of the diff\nexactly. So you are not necessarily finding the fork point, but rather\nan appropriate place to apply the patch.\n\nI have to wonder, though, whether it is worth the trouble. If you apply\nthe patch to your tip, especially using \"git am -3\", then one of two\nthings will happen:\n\n  1. The patch will apply cleanly. Either because your tip matched the\n     preimage exactly, or because it was close enough and git was able\n     to apply anyway.\n\n  2. There are conflicts between what you did and what the patch does.\n     In this case, though, what you are doing by searching for the fork\n     point will recreate the history locally that your collaborator has.\n     But when you go to merge their history, you will end up getting the\n     exact same conflicts that you would if you applied to your tip now.\n\nSo what is the value in applying their patch to the original fork point?\nIt better represents the history of what happened. But if you care about\nthat, I wonder if you should just be pulling from them directly via git\n(or if that isn't convenient for some reason, passing around bundles).\n\n> To find the place where the patch applies, I then would run something like\n> \n> git rev-list --all | \\\n> while read commit; do \\\n> \tgit ls-tree -r $commit | \\\n> \tawk \"$(perl ~/programs/git-hacks/create_awk.pl < <patch file>)\" > /dev/null || \\\n> \techo $commit; \\\n> done\n\nWow, dynamically generating awk using perl. That's a new one for me. :)\n\n-Peff\n"},{"id":"167179","messageId":"20110505201204.GA31572@nwp-laptop","threadId":"27275","inReplyTo":"20110505195556.GA1770@sigill.intra.peff.net","subject":"Re: How to efficiently find where a patch applies?","fromName":"Nathan W. Panike","fromEmail":"nathan.panike@gmail.com","sentAt":"2011-05-05T20:12:05Z","receivedAt":"2011-05-05T20:12:05Z","isPatch":false,"sender":{"key":"nathan.panike@gmail.com","avatar":"https://avatars.githubusercontent.com/u/389447?v=4"},"body":"On Thu, May 05, 2011 at 03:55:56PM -0400, Jeff King wrote:\n> On Thu, May 05, 2011 at 01:17:41PM -0500, Nathan W. Panike wrote:\n> \n> > In the past couple weeks, I have had several occasions where a collaborator has\n> > sent a patch, which does not have information about where the patch forked from\n> > master.  I wrote the following scripts to try to discover where the patch\n> > should be applied.  Is there a better way?\n> \n> What you have is more or less the best way. As you probably realized,\n> there could be any number of commits that match the preimage of the diff\n> exactly. So you are not necessarily finding the fork point, but rather\n> an appropriate place to apply the patch.\n\nYes.  I thought there might be some feature of git-apply that would help me,\nbut now I will stop thinking that.\n\n> \n> I have to wonder, though, whether it is worth the trouble. If you apply\n> the patch to your tip, especially using \"git am -3\", then one of two\n> things will happen:\n> \n>   1. The patch will apply cleanly. Either because your tip matched the\n>      preimage exactly, or because it was close enough and git was able\n>      to apply anyway.\n> \n>   2. There are conflicts between what you did and what the patch does.\n>      In this case, though, what you are doing by searching for the fork\n>      point will recreate the history locally that your collaborator has.\n>      But when you go to merge their history, you will end up getting the\n>      exact same conflicts that you would if you applied to your tip now.\n> \n\nThe patches were emailed as raw diffs, not as format-patch messages, so I\nthought git-am was not applicable. Also, I was applying the patches to the git\nrepository on behalf of local colleagues when they ran into problems using\n'git-apply'.  I did not want to deal with merge conflicts---my colleagues can\nhandle the conflicts themselves. So a clean merge was optimal from my\nperspective.\n\n> So what is the value in applying their patch to the original fork point?\n> It better represents the history of what happened. But if you care about\n> that, I wonder if you should just be pulling from them directly via git\n> (or if that isn't convenient for some reason, passing around bundles).\n> \n\nOh, I keep forgetting about bundles.  Next time, I might ask them to send a\nbundle rather than a patch or ask them to use format-patch.\n\n> Wow, dynamically generating awk using perl. That's a new one for me. :)\n\nYou might say it is awk-ward.\n\nThanks,\n\nNathan Panike\n\n> \n> -Peff\n"},{"id":"167180","messageId":"20110505201718.GA2533@sigill.intra.peff.net","threadId":"27275","inReplyTo":"20110505201204.GA31572@nwp-laptop","subject":"Re: How to efficiently find where a patch applies?","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-05-05T20:17:18Z","receivedAt":"2011-05-05T20:17:18Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, May 05, 2011 at 03:12:05PM -0500, Nathan W. Panike wrote:\n\n> The patches were emailed as raw diffs, not as format-patch messages, so I\n> thought git-am was not applicable. Also, I was applying the patches to the git\n> repository on behalf of local colleagues when they ran into problems using\n> 'git-apply'.\n\nGit-am is basically just a wrapper around git-apply that will split an\nemail message into a raw diff and a commit message. If you have raw\ndiffs in an email, it may handle them OK, or it may be simple enough to\nmassage them into the right form.\n\nAs far as I know, there isn't a convenient way to get \"git apply\" to do\nthe same merge magic for a raw diff that \"git am -3\" does. It should be\npossible, as the only relevant input is the raw diff; I just don't think\nanybody has bothered to do it.\n\n> I did not want to deal with merge conflicts---my colleagues can\n> handle the conflicts themselves. So a clean merge was optimal from my\n> perspective.\n\nAh, that makes more sense. I have been in a similar \"helping people with\ngit\" situation myself.\n\n> > Wow, dynamically generating awk using perl. That's a new one for me. :)\n> You might say it is awk-ward.\n\nOuch. :)\n\n-Peff\n"}]}