{"thread":{"id":"27058","subject":"Converting merge to rebase in the presence of conflicts","startedAt":"2011-04-11T14:13:53Z","lastAt":"2011-04-12T06:11:09Z","messageCount":6,"participants":["Hrvoje Nikšić","Michael J Gruber","Johannes Sixt","Michael Haggerty"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"165622","messageId":"BANLkTi=krC6JMEWj=a5CY1vRCcmh9b+BaQ@mail.gmail.com","threadId":"27058","inReplyTo":null,"subject":"Converting merge to rebase in the presence of conflicts","fromName":"Hrvoje Nikšić","fromEmail":"hniksic@gmail.com","sentAt":"2011-04-11T14:13:53Z","receivedAt":"2011-04-11T14:13:53Z","isPatch":false,"sender":{"key":"hniksic@gmail.com","avatar":"https://gravatar.com/avatar/a48579783560f9745ebcec8d2545f4f346ebad7a7dd58455536fc3263cfcea0a?d=mp&s=160"},"body":"Is it possible to convert a merge with (resolved) conflicts into a rebase?\n\nI find it useful to always pull commits with \"git pull\" because it is\nless intrusive on my local commits (if any) than \"git pull --rebase\",\nand it provides a nicer change summary. Also, conflict resolution\nseems more intuitive when merging than when rebasing. And If I decide\nlater to rebase after all, I can simply issue \"git rebase origin/bla\".\nAs long as there are no conflicts.\n\nIf the merge resolves conflicts, the subsequent rebase is unaware of\nthat, and the conflicts must be resolved once more. Here is an example\nin a single repository that just uses 'merge' to show the scenario:\n\n# create a common file with two lines and branch off\nprintf 'foo\\nbar\\n' > a\ngit add a && git commit -m '' a\ngit add a && git commit -m 'Added.' a\ngit branch somebranch\n\n# now work on the file in both branches\necho baz >> a\ngit commit -m changed a\ngit checkout somebranch\necho qux >> a\ngit commit -m changed2 a\n\n# we're on somebranch and decide to merge our changes with master:\ngit merge master\nvi a           # resolve conflicts\ngit add a\ngit commit     # commit the merge\n\nAt this point say the developer on somebranch changes his mind and\nwants to rebase after all. The result is, again, a conflict:\n\n# try to change merge to rebase\ngit rebase master\n[... long output on conflicts ...]\n\nFirst, rewinding head to replay your work on top of it...\nApplying: changed2\nUsing index info to reconstruct a base tree...\nFalling back to patching base and 3-way merge...\nAuto-merging a\nCONFLICT (content): Merge conflict in a\nFailed to merge in the changes.\nPatch failed at 0001 changed2\n\nWhen you have resolved this problem run \"git rebase --continue\".\nIf you would prefer to skip this patch, instead run \"git rebase --skip\".\nTo restore the original branch and stop rebasing run \"git rebase --abort\".\n\n\nIs there a way to rebase the branch without redoing conflict\nresolution? Some option to rebase, or a trick with rebase -i? The\nconflict resolution must obviously go into some commit, it would be\nnice to be able to choose whether to amend an existing commit with the\nadditional changes or to add a new commit.\n\nHrvoje\n"},{"id":"165624","messageId":"4DA312AF.80100@drmicha.warpmail.net","threadId":"27058","inReplyTo":"BANLkTi=krC6JMEWj=a5CY1vRCcmh9b+BaQ@mail.gmail.com","subject":"Re: Converting merge to rebase in the presence of conflicts","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2011-04-11T14:39:43Z","receivedAt":"2011-04-11T14:39:43Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Hrvoje Nikšić venit, vidit, dixit 11.04.2011 16:13:\n> Is it possible to convert a merge with (resolved) conflicts into a rebase?\n> \n> I find it useful to always pull commits with \"git pull\" because it is\n> less intrusive on my local commits (if any) than \"git pull --rebase\",\n> and it provides a nicer change summary. Also, conflict resolution\n> seems more intuitive when merging than when rebasing. And If I decide\n> later to rebase after all, I can simply issue \"git rebase origin/bla\".\n> As long as there are no conflicts.\n> \n> If the merge resolves conflicts, the subsequent rebase is unaware of\n> that, and the conflicts must be resolved once more. Here is an example\n> in a single repository that just uses 'merge' to show the scenario:\n> \n> # create a common file with two lines and branch off\n> printf 'foo\\nbar\\n' > a\n> git add a && git commit -m '' a\n> git add a && git commit -m 'Added.' a\n> git branch somebranch\n> \n> # now work on the file in both branches\n> echo baz >> a\n> git commit -m changed a\n> git checkout somebranch\n> echo qux >> a\n> git commit -m changed2 a\n> \n> # we're on somebranch and decide to merge our changes with master:\n> git merge master\n> vi a           # resolve conflicts\n> git add a\n> git commit     # commit the merge\n> \n> At this point say the developer on somebranch changes his mind and\n> wants to rebase after all. The result is, again, a conflict:\n> \n> # try to change merge to rebase\n> git rebase master\n> [... long output on conflicts ...]\n> \n> First, rewinding head to replay your work on top of it...\n> Applying: changed2\n> Using index info to reconstruct a base tree...\n> Falling back to patching base and 3-way merge...\n> Auto-merging a\n> CONFLICT (content): Merge conflict in a\n> Failed to merge in the changes.\n> Patch failed at 0001 changed2\n> \n> When you have resolved this problem run \"git rebase --continue\".\n> If you would prefer to skip this patch, instead run \"git rebase --skip\".\n> To restore the original branch and stop rebasing run \"git rebase --abort\".\n> \n> \n> Is there a way to rebase the branch without redoing conflict\n> resolution? Some option to rebase, or a trick with rebase -i? The\n> conflict resolution must obviously go into some commit, it would be\n> nice to be able to choose whether to amend an existing commit with the\n> additional changes or to add a new commit.\n> \n> Hrvoje\n\nIf you enable rerere before the merge then the merge resolution is\nrecorded and can be reused by rebase. It still stops but applied the\nprevious resolution automatically already.\n\nMichael\n"},{"id":"165625","messageId":"4DA3182B.2030305@viscovery.net","threadId":"27058","inReplyTo":"BANLkTi=krC6JMEWj=a5CY1vRCcmh9b+BaQ@mail.gmail.com","subject":"Re: Converting merge to rebase in the presence of conflicts","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2011-04-11T15:03:07Z","receivedAt":"2011-04-11T15:03:07Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Am 4/11/2011 16:13, schrieb Hrvoje Nikšić:\n> Is there a way to rebase the branch without redoing conflict\n> resolution?\n\ngit config --global rerere.enabled true\n\n-- Hannes\n"},{"id":"165626","messageId":"BANLkTinVUdmG56oPQXvMhFh6hLcFj3_jZg@mail.gmail.com","threadId":"27058","inReplyTo":"4DA3182B.2030305@viscovery.net","subject":"Re: Converting merge to rebase in the presence of conflicts","fromName":"Hrvoje Nikšić","fromEmail":"hniksic@gmail.com","sentAt":"2011-04-11T15:15:11Z","receivedAt":"2011-04-11T15:15:11Z","isPatch":false,"sender":{"key":"hniksic@gmail.com","avatar":"https://gravatar.com/avatar/a48579783560f9745ebcec8d2545f4f346ebad7a7dd58455536fc3263cfcea0a?d=mp&s=160"},"body":"Thanks for the responses, rerere works nicely, if somewhat cryptic. At\nthe rebase step I got:\n\nFirst, rewinding head to replay your work on top of it...\nApplying: changed2\nUsing index info to reconstruct a base tree...\nFalling back to patching base and 3-way merge...\nAuto-merging a\nCONFLICT (content): Merge conflict in a\nResolved 'a' using previous resolution.\nFailed to merge in the changes.\nPatch failed at 0001 changed2\n\nWhen you have resolved this problem run \"git rebase --continue\".\nIf you would prefer to skip this patch, instead run \"git rebase --skip\".\nTo restore the original branch and stop rebasing run \"git rebase --abort\".\n\nThat's a lot of output, some of it scary-looking. (OK, maybe not\nscary-looking to me, but certainly so to someone not yet fully\ncomfortable with git.)  Running \"git rebase --continue\" told me I\nneeded to \"edit all merge conflicts and then mark them as resolved\",\nwhereas the conflicts are in fact already resolved, but rebase doesn't\nknow it.  Again, this isn't a big problem for me, but it's unfriendly.\n \"git add\" followed by \"git rebase --continue\" worked exactly as I\nhoped it would.\n\nI still wonder why rerere is necessary here. After all, even without\nthe rerere metadata, the information about conflict resolution is\nright there, in the merge commit, and rebase could conceivably make\nuse of it. What am I missing?\n\nHrvoje\n"},{"id":"165662","messageId":"4DA3BF1A.7030407@alum.mit.edu","threadId":"27058","inReplyTo":"BANLkTinVUdmG56oPQXvMhFh6hLcFj3_jZg@mail.gmail.com","subject":"Re: Converting merge to rebase in the presence of conflicts","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-04-12T02:55:22Z","receivedAt":"2011-04-12T02:55:22Z","isPatch":false,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"On 04/11/2011 05:15 PM, Hrvoje Nikšić wrote:\n> [...]\n> I still wonder why rerere is necessary here. After all, even without\n> the rerere metadata, the information about conflict resolution is\n> right there, in the merge commit, and rebase could conceivably make\n> use of it. What am I missing?\n\nIn general, merge and rebase are quite different animals.  In the\nexample you provided, there was only one conflicting commit being\nrebased, so the difference is not so apparent.\n\nOne commit merged:\n\n*--*--a--m      \"master\"\n    \\   /\n     b--\n\nOne commit rebased:\n\n*--*--a                           *--*--a--b'        \"master\"\n    \\              ->\n     b\n\nIn either case, \"git diff a..master\" is identical.  Therefore,\nconverting \"one commit merged\" into \"one commit rebased\" simply involves\nforgetting the second parent of commit \"m\".  The \"rerere\" facility will\nindeed help you here, as other people have suggested.\n\nBut if more than one commit is being brought in from the branch, then\nmerge and rebase are more distinct.  Merge forces you to resolve the\nconflicts only once, in a single merge commit, whereas rebase forces you\nto resolve the conflicts one commit at a time.\n\nMultiple commits merged:\n\n*--*--a---M      \"master\"\n    \\    /\n     b--c\n\nMultiple commits rebased:\n\n*--*--a                          *--*--a--b'--c'     \"master\"\n    \\              ->\n     b--c\n\nIt should still be that \"git diff a..master\" gives identical results in\nthe two cases, but there is still a big difference--in the rebase\nexample, master after commit \"b'\" should be a functional state that can\nbe compiled and passes the unit tests.  The state at commit \"b'\"\nincludes a combination of the changes made in \"a\" plus the changes made\nin the original \"b\".  In the merge example, there is no state of the\ntree that is equivalent; there is only a+b+c.  This lack of intermediate\nconflict resolution is what makes merges problematic for \"git bisect\".\n\nNow, you want a way to transform the merge into a rebase automatically.\n In other words, given the information in the \"multiple commits merged\"\nexample as raw material, how can you convert it into a rebase?  This is\nonly possible if you are willing to squash \"b\", \"c\", and \"M\" into a\nsingle commit:\n\n*--*--a--bcM\n\nbecause you have only told git how to resolve the conflicts between \"a\"\nand \"b+c\", not between \"a\" and \"b\" without \"c\".\n\nThis is why I have advocated \"rebase with history\" [1], which retains\nboth the intermediate conflict resolutions and also the merge information:\n\n*--*--a--b'--c'     \"master\"\n    \\   /   /\n     --b---c\n\nMichael\n\n[1]\nhttp://softwareswirl.blogspot.com/2009/04/truce-in-merge-vs-rebase-war.html\n\n-- \nMichael Haggerty\nmhagger@alum.mit.edu\nhttp://softwareswirl.blogspot.com/\n"},{"id":"165663","messageId":"4DA3ECFD.7060202@viscovery.net","threadId":"27058","inReplyTo":"BANLkTinVUdmG56oPQXvMhFh6hLcFj3_jZg@mail.gmail.com","subject":"Re: Converting merge to rebase in the presence of conflicts","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2011-04-12T06:11:09Z","receivedAt":"2011-04-12T06:11:09Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Please don't cull Cc list; use \"Reply to all\" in your MUA.\n\nAm 4/11/2011 17:15, schrieb Hrvoje Nikšić:\n> I still wonder why rerere is necessary here. After all, even without\n> the rerere metadata, the information about conflict resolution is\n> right there, in the merge commit, and rebase could conceivably make\n> use of it. What am I missing?\n\nThe conflicts that you see during a merge may be attributed to several\ndifferent commits of the merged branch. Therefore, when you rebase the\nbranch, you will see different subsets of the conflicts for each rebased\ncommit, and it is possible that you see conflicts that you did not see in\nthe merge. How can you expect rebase to \"know\" how to resolve them?\n\n-- Hannes\n"}]}