{"thread":{"id":"33084","subject":"feature suggestion: improve rerere","startedAt":"2013-03-06T10:16:40Z","lastAt":"2013-03-07T07:05:07Z","messageCount":4,"participants":["Uwe Kleine-König","Johannes Sixt"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"210685","messageId":"20130306101640.GA15375@pengutronix.de","threadId":"33084","inReplyTo":null,"subject":"feature suggestion: improve rerere","fromName":"Uwe Kleine-König","fromEmail":"u.kleine-koenig@pengutronix.de","sentAt":"2013-03-06T10:16:40Z","receivedAt":"2013-03-06T10:16:40Z","isPatch":false,"sender":{"key":"u.kleine-koenig@pengutronix.de","avatar":"https://gravatar.com/avatar/354b5e3ceb2806a2f1e1e382ac29ddbdad18288654da62b61eb13583a857eee7?d=mp&s=160"},"body":"Hello,\n\nI think the following suggestion is sound. And it might even be easy to\nimplement but I don't know how rerere works, so I might be wrong here.\n\nWhen applying a patch it's normal to hit a conflict. For me this just\nhappend:\n\n\t$ git diff\n\tdiff --cc flash_otp_write.c\n\tindex f360a3e,648e042..0000000\n\t--- a/flash_otp_write.c\n\t+++ b/flash_otp_write.c\n\t@@@ -15,8 -15,23 +15,29 @@@\n\t  \n\t  #include <mtd/mtd-user.h>\n\t  \n\t++<<<<<<< ours\n\t +#include \"common.h\"\n\t +\n\t++||||||| base\n\t++=======\n\t+ ssize_t xread(int fd, void *buf, size_t count)\n\t+ {\n\t+ \tssize_t ret, done = 0;\n\t+ \n\t+ retry:\n\t+ \tret = read(fd, buf + done, count - done);\n\t+ \tif (ret < 0)\n\t+ \t\treturn ret;\n\t+ \n\t+ \tdone += ret;\n\t+ \n\t+ \tif (ret == 0 /* EOF */ || done == count)\n\t+ \t\treturn done;\n\t+ \telse\n\t+ \t\tgoto retry;\n\t+ }\n\t+ \n\t++>>>>>>> theirs\n\t  int main(int argc,char *argv[])\n\t  {\n\t\tint fd, val, ret, size, wrote, len;\n\neasy to resolve to:\n\n\t$ git diff\n\tdiff --cc flash_otp_write.c\n\tindex f360a3e,648e042..0000000\n\t--- a/flash_otp_write.c\n\t+++ b/flash_otp_write.c\n\t@@@ -15,8 -15,23 +15,25 @@@\n\t  \n\t  #include <mtd/mtd-user.h>\n\t  \n\t +#include \"common.h\"\n\t +\n\t+ ssize_t xread(int fd, void *buf, size_t count)\n\t+ {\n\t+ \tssize_t ret, done = 0;\n\t+ \n\t+ retry:\n\t+ \tret = read(fd, buf + done, count - done);\n\t+ \tif (ret < 0)\n\t+ \t\treturn ret;\n\t+ \n\t+ \tdone += ret;\n\t+ \n\t+ \tif (ret == 0 /* EOF */ || done == count)\n\t+ \t\treturn done;\n\t+ \telse\n\t+ \t\tgoto retry;\n\t+ }\n\t+ \n\t  int main(int argc,char *argv[])\n\t  {\n\t\tint fd, val, ret, size, wrote, len;\n\nNow if I shuffle patches and put the new patch before the conflicting\npatch, I have to resolve first:\n\n\t$ git diff\n\tdiff --cc flash_otp_write.c\n\tindex d407ebb,31b963e..0000000\n\t--- a/flash_otp_write.c\n\t+++ b/flash_otp_write.c\n\t@@@ -15,6 -15,25 +15,31 @@@\n\t  \n\t  #include <mtd/mtd-user.h>\n\t  \n\t++<<<<<<< ours\n\t++||||||| base\n\t++#include \"common.h\"\n\t++\n\t++=======\n\t+ #include \"common.h\"\n\t+ \n\t+ ssize_t xread(int fd, void *buf, size_t count)\n\t+ {\n\t+ \tssize_t ret, done = 0;\n\t+ \n\t+ retry:\n\t+ \tret = read(fd, buf + done, count - done);\n\t+ \tif (ret < 0)\n\t+ \t\treturn ret;\n\t+ \n\t+ \tdone += ret;\n\t+ \n\t+ \tif (ret == 0 /* EOF */ || done == count)\n\t+ \t\treturn done;\n\t+ \telse\n\t+ \t\tgoto retry;\n\t+ }\n\t+ \n\t++>>>>>>> theirs\n\t  int main(int argc,char *argv[])\n\t  {\n\t\tint fd, val, ret, size, wrote, len;\n\nwhich is resolved to just adding the function and dropping the #include.\nBut then readding the 2nd patch it conflicts again:\n\n\t$ git diff\n\tdiff --cc flash_otp_write.c\n\tindex 648e042,f360a3e..0000000\n\t--- a/flash_otp_write.c\n\t+++ b/flash_otp_write.c\n\t@@@ -15,23 -15,8 +15,29 @@@\n\t  \n\t  #include <mtd/mtd-user.h>\n\t  \n\t++<<<<<<< ours\n\t +ssize_t xread(int fd, void *buf, size_t count)\n\t +{\n\t +\tssize_t ret, done = 0;\n\t +\n\t +retry:\n\t +\tret = read(fd, buf + done, count - done);\n\t +\tif (ret < 0)\n\t +\t\treturn ret;\n\t +\n\t +\tdone += ret;\n\t +\n\t +\tif (ret == 0 /* EOF */ || done == count)\n\t +\t\treturn done;\n\t +\telse\n\t +\t\tgoto retry;\n\t +}\n\t +\n\t++||||||| base\n\t++=======\n\t+ #include \"common.h\"\n\t+ \n\t++>>>>>>> theirs\n\t  int main(int argc,char *argv[])\n\t  {\n\t\tint fd, val, ret, size, wrote, len;\n\nThis is the same conflict as the first one, just with ours and theirs\nexchanged. So my suggestion is to make rerere use the resolution\nrecorded for the first conflict here.\n\nSounds sensible?\n\nBest regards\nUwe\n\nPS: I'm using Debian's git 1.8.2~rc2-1 and hope I didn't miss this\nfeature already implemented while looking through v1.8.2..junio/next.\n\n-- \nPengutronix e.K.                           | Uwe Kleine-König            |\nIndustrial Linux Solutions                 | http://www.pengutronix.de/  |\n"},{"id":"210697","messageId":"51374382.6050101@viscovery.net","threadId":"33084","inReplyTo":"20130306101640.GA15375@pengutronix.de","subject":"Re: feature suggestion: improve rerere","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2013-03-06T13:24:18Z","receivedAt":"2013-03-06T13:24:18Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Am 3/6/2013 11:16, schrieb Uwe Kleine-König:\n> \t++<<<<<<< ours\n> \t +ssize_t xread(int fd, void *buf, size_t count)\n> \t +{\n> \t +\tssize_t ret, done = 0;\n> \t +\n> \t +retry:\n> \t +\tret = read(fd, buf + done, count - done);\n> \t +\tif (ret < 0)\n> \t +\t\treturn ret;\n> \t +\n> \t +\tdone += ret;\n> \t +\n> \t +\tif (ret == 0 /* EOF */ || done == count)\n> \t +\t\treturn done;\n> \t +\telse\n> \t +\t\tgoto retry;\n> \t +}\n> \t +\n> \t++||||||| base\n> \t++=======\n> \t+ #include \"common.h\"\n> \t+ \n> \t++>>>>>>> theirs\n> \t  int main(int argc,char *argv[])\n> \t  {\n> \t\tint fd, val, ret, size, wrote, len;\n> \n> This is the same conflict as the first one, just with ours and theirs\n> exchanged. So my suggestion is to make rerere use the resolution\n> recorded for the first conflict here.\n> \n> Sounds sensible?\n\nOf course, and rerere already does it. But only when you use git's default\nconflict markers rather than diff3 style markers that have this extra\n||||| line.\n\n-- Hannes\n"},{"id":"210699","messageId":"20130306144225.GB15375@pengutronix.de","threadId":"33084","inReplyTo":"51374382.6050101@viscovery.net","subject":"Re: feature suggestion: improve rerere","fromName":"Uwe Kleine-König","fromEmail":"u.kleine-koenig@pengutronix.de","sentAt":"2013-03-06T14:42:25Z","receivedAt":"2013-03-06T14:42:25Z","isPatch":false,"sender":{"key":"u.kleine-koenig@pengutronix.de","avatar":"https://gravatar.com/avatar/354b5e3ceb2806a2f1e1e382ac29ddbdad18288654da62b61eb13583a857eee7?d=mp&s=160"},"body":"On Wed, Mar 06, 2013 at 02:24:18PM +0100, Johannes Sixt wrote:\n> Am 3/6/2013 11:16, schrieb Uwe Kleine-König:\n> > \t++<<<<<<< ours\n> > \t +ssize_t xread(int fd, void *buf, size_t count)\n> > \t +{\n> > \t +\tssize_t ret, done = 0;\n> > \t +\n> > \t +retry:\n> > \t +\tret = read(fd, buf + done, count - done);\n> > \t +\tif (ret < 0)\n> > \t +\t\treturn ret;\n> > \t +\n> > \t +\tdone += ret;\n> > \t +\n> > \t +\tif (ret == 0 /* EOF */ || done == count)\n> > \t +\t\treturn done;\n> > \t +\telse\n> > \t +\t\tgoto retry;\n> > \t +}\n> > \t +\n> > \t++||||||| base\n> > \t++=======\n> > \t+ #include \"common.h\"\n> > \t+ \n> > \t++>>>>>>> theirs\n> > \t  int main(int argc,char *argv[])\n> > \t  {\n> > \t\tint fd, val, ret, size, wrote, len;\n> > \n> > This is the same conflict as the first one, just with ours and theirs\n> > exchanged. So my suggestion is to make rerere use the resolution\n> > recorded for the first conflict here.\n> > \n> > Sounds sensible?\n> \n> Of course, and rerere already does it. But only when you use git's default\n> conflict markers rather than diff3 style markers that have this extra\n> ||||| line.\nI only did git checkout --conflict=diff3 after the merge conflict\nhappend. So I cannot confirm that git already does it.\n\nSo here is a reproduction receipe:\n\n\tgit clone git://git.infradead.org/mtd-utils.git\n\tcd mtd-utils\n\tgit checkout ca39eb1\n\twget -O patch1 http://article.gmane.org/gmane.linux.drivers.mtd/45779/raw\n\twget -O patch2 http://article.gmane.org/gmane.linux.drivers.mtd/45591/raw\n\tfor p in patch1 patch2; do perl -p -i -e 'print \"From tralala Mon Sep 17 00:00:00 2001\\n\" if $. == 1' $p; done\n\tgit am patch1\n\tgit am -3 patch2 # first merge conflict\n\tperl -n -i -e 's/=======//; print unless /^[<>]{7} /;' flash_otp_write.c # resolve\n\tgit add flash_otp_write.c\n\tgit am --resolved\n\tgit rebase -i ca39eb1 # swap order of the two patches\n\nresults in\n\n\t$ git ls-files -u\n\t100644 f360a3e025deaf7acfb7b20c9fad90f498ae4430 1\tflash_otp_write.c\n\t100644 d407ebbf400e630dc00ee004ecb44be8af51b25d 2\tflash_otp_write.c\n\t100644 31b963e2d6cf0016ca542529886e1ee71a22664e 3\tflash_otp_write.c\n\nand resolving yields:\n\n\t$ git ls-files -s flash_otp_write.c\n\t100644 648e0422d21c0ffa7621f82b86c02a065e488293 0\tflash_otp_write.c\n\nThen\n\tgit rebase --continue \n\ngives the 2nd rebase conflict:\n\n\t$ git ls-files -u\n\t100644 d407ebbf400e630dc00ee004ecb44be8af51b25d 1\tflash_otp_write.c\n\t100644 648e0422d21c0ffa7621f82b86c02a065e488293 2\tflash_otp_write.c\n\t100644 f360a3e025deaf7acfb7b20c9fad90f498ae4430 3\tflash_otp_write.c\n\nNow knowing from the previous resolution that with base=f360a3e0\n(= origin + patch1) merging\n\n\td407ebbf (= origin) and\n\t31b963e2 (= origin + patch1 + patch2)\n\ngives 648e0422 (origin + patch2),\ngit could know that with base=d407ebbf (origin) merging 648e0422 (origin\n+ patch1) and f360a3e0 (origin + patch1) gives 31b963e2 (origin + patch1\n+ patch2) again.\n\nAnd git doesn't prepare 31b963e2 in flash_otp_write.c for me.\n\n@Johannes, do you have some non-standard setting, or can you reproduce?\n\nBest regards\nUwe\n\n-- \nPengutronix e.K.                           | Uwe Kleine-König            |\nIndustrial Linux Solutions                 | http://www.pengutronix.de/  |\n"},{"id":"210746","messageId":"51383C23.2090900@viscovery.net","threadId":"33084","inReplyTo":"20130306144225.GB15375@pengutronix.de","subject":"Re: feature suggestion: improve rerere","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2013-03-07T07:05:07Z","receivedAt":"2013-03-07T07:05:07Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Am 3/6/2013 15:42, schrieb Uwe Kleine-König:\n> On Wed, Mar 06, 2013 at 02:24:18PM +0100, Johannes Sixt wrote:\n>> Am 3/6/2013 11:16, schrieb Uwe Kleine-König:\n>>> \t++<<<<<<< ours\n>>> \t +ssize_t xread(int fd, void *buf, size_t count)\n>>> \t +{\n>>> \t +\tssize_t ret, done = 0;\n>>> \t +\n>>> \t +retry:\n>>> \t +\tret = read(fd, buf + done, count - done);\n>>> \t +\tif (ret < 0)\n>>> \t +\t\treturn ret;\n>>> \t +\n>>> \t +\tdone += ret;\n>>> \t +\n>>> \t +\tif (ret == 0 /* EOF */ || done == count)\n>>> \t +\t\treturn done;\n>>> \t +\telse\n>>> \t +\t\tgoto retry;\n>>> \t +}\n>>> \t +\n>>> \t++||||||| base\n>>> \t++=======\n>>> \t+ #include \"common.h\"\n>>> \t+ \n>>> \t++>>>>>>> theirs\n>>> \t  int main(int argc,char *argv[])\n>>> \t  {\n>>> \t\tint fd, val, ret, size, wrote, len;\n>>>\n>>> This is the same conflict as the first one, just with ours and theirs\n>>> exchanged. So my suggestion is to make rerere use the resolution\n>>> recorded for the first conflict here.\n>>>\n>>> Sounds sensible?\n>>\n>> Of course, and rerere already does it. But only when you use git's default\n>> conflict markers rather than diff3 style markers that have this extra\n>> ||||| line.\n> I only did git checkout --conflict=diff3 after the merge conflict\n> happend. So I cannot confirm that git already does it.\n> \n> So here is a reproduction receipe:\n> \n> \tgit clone git://git.infradead.org/mtd-utils.git\n> \tcd mtd-utils\n> \tgit checkout ca39eb1\n> \twget -O patch1 http://article.gmane.org/gmane.linux.drivers.mtd/45779/raw\n> \twget -O patch2 http://article.gmane.org/gmane.linux.drivers.mtd/45591/raw\n\nAt least patch2 has incorret index information; it does not apply with am\n-3. I generated a working version with format-patch after applying it\ndirectly on top of ca39eb1.\n\n> \tfor p in patch1 patch2; do perl -p -i -e 'print \"From tralala Mon Sep 17 00:00:00 2001\\n\" if $. == 1' $p; done\n\nDo you have rerere enabled at this point?\n\n\tgit config rerere.enabled true\n\n> \tgit am patch1\n> \tgit am -3 patch2 # first merge conflict\n> \tperl -n -i -e 's/=======//; print unless /^[<>]{7} /;' flash_otp_write.c # resolve\n> \tgit add flash_otp_write.c\n> \tgit am --resolved\n> \tgit rebase -i ca39eb1 # swap order of the two patches\n> \n> results in\n> \n> \t$ git ls-files -u\n> \t100644 f360a3e025deaf7acfb7b20c9fad90f498ae4430 1\tflash_otp_write.c\n> \t100644 d407ebbf400e630dc00ee004ecb44be8af51b25d 2\tflash_otp_write.c\n> \t100644 31b963e2d6cf0016ca542529886e1ee71a22664e 3\tflash_otp_write.c\n\nSame here.\n\n> \n> and resolving yields:\n> \n> \t$ git ls-files -s flash_otp_write.c\n> \t100644 648e0422d21c0ffa7621f82b86c02a065e488293 0\tflash_otp_write.c\n\nOK.\n\n> \n> Then\n> \tgit rebase --continue \n> \n> gives the 2nd rebase conflict:\n> \n> \t$ git ls-files -u\n> \t100644 d407ebbf400e630dc00ee004ecb44be8af51b25d 1\tflash_otp_write.c\n> \t100644 648e0422d21c0ffa7621f82b86c02a065e488293 2\tflash_otp_write.c\n> \t100644 f360a3e025deaf7acfb7b20c9fad90f498ae4430 3\tflash_otp_write.c\n\nSame here.\n\n> \n> Now knowing from the previous resolution that with base=f360a3e0\n> (= origin + patch1) merging\n> \n> \td407ebbf (= origin) and\n> \t31b963e2 (= origin + patch1 + patch2)\n> \n> gives 648e0422 (origin + patch2),\n> git could know that with base=d407ebbf (origin) merging 648e0422 (origin\n> + patch1) and f360a3e0 (origin + patch1) gives 31b963e2 (origin + patch1\n> + patch2) again.\n\nFor me, it works as expected, i.e., I get the conflict resolved by rerere.\n\n> \n> And git doesn't prepare 31b963e2 in flash_otp_write.c for me.\n> \n> @Johannes, do you have some non-standard setting, or can you reproduce?\n\nPerhaps:\n\n$ git config --global -l | grep rerere\nrerere.enabled=true\n\n-- Hannes\n"}]}