{"thread":{"id":"15574","subject":"Help breaking up a large merge.","startedAt":"2008-09-18T15:21:55Z","lastAt":"2008-09-18T17:47:05Z","messageCount":6,"participants":["David Brown","Santi Béjar","Johannes Sixt","Avery Pennarun"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"91031","messageId":"20080918152154.GA27019@linode.davidb.org","threadId":"15574","inReplyTo":null,"subject":"Help breaking up a large merge.","fromName":"David Brown","fromEmail":"git@davidb.org","sentAt":"2008-09-18T15:21:55Z","receivedAt":"2008-09-18T15:21:55Z","isPatch":false,"sender":{"key":"git@davidb.org","avatar":"https://gravatar.com/avatar/94c86a2938470a74c2eac5e2b69afc0871f79a660295c02219597aba8cb101c1?d=mp&s=160"},"body":"Say we have a tree that we've been working on for a few months.  An\noutside vendor has also been working on the same tree during this\ntime, and we need to merge with their work.\n\nThe difficulty I'm having is that there are a lot of conflicts\nresulting from the merge (expected), and it would be nice to somehow\nbe able to work on a smaller set of these conflicts at a time.\n\nSome of the conflicts are caused by a single change in the other tree.\nThis is easy to cherry-pick into my tree, resolve, and then test those\nchanges independently.\n\nBut other conflicts are caused by groups of commits that are\ninterleaved with others.\n\nIdeally, I'd like to be able to divide this conflict resolution work\nup among a small group of people, have everybody work on part, test\ntheir part, and then I could bring all of the resolved versions\ntogether, test that, and make that the actual merge commit in our\nrepo.  I've had a few ideas, but none really seem to work all that\nwell.\n\n   - Do \"git merge -s ours their-tree\".  Then, in another branch try\n     the merge, and resolve a group of files that go together.  Put\n     these into the 'ours' tree and ammend these changes to the merge\n     commit.  The problem here is that this misses all of the merges\n     that would happen automatically.\n\n   - \"git branch -b tmp $(git merge-base our-head their-tree)\", and\n     then: \"git checkout their-tree filenames\" for a small group of\n     conflicting files.  Commit this, then in my regular tree, cherry\n     pick this change and resolve the conflict.  Then, when finally\n     doing the merge with their tree, these files can be resolved by\n     just using our version.  This still requires doing some tracking.\n\nAny other ideas?\n\nIn the future, we're going to try and work more closely with the\nvendor, but we have to get to the point of having something common to\nstart that.\n\nThanks,\nDavid\n"},{"id":"91035","messageId":"adf1fd3d0809180855l42af4fb6l67275daef0d2a529@mail.gmail.com","threadId":"15574","inReplyTo":"20080918152154.GA27019@linode.davidb.org","subject":"Re: Help breaking up a large merge.","fromName":"Santi Béjar","fromEmail":"santi@agolina.net","sentAt":"2008-09-18T15:55:34Z","receivedAt":"2008-09-18T15:55:34Z","isPatch":false,"sender":{"key":"santi@agolina.net","avatar":null},"body":"On Thu, Sep 18, 2008 at 5:21 PM, David Brown <git@davidb.org> wrote:\n> Say we have a tree that we've been working on for a few months.  An\n> outside vendor has also been working on the same tree during this\n> time, and we need to merge with their work.\n>\n> The difficulty I'm having is that there are a lot of conflicts\n> resulting from the merge (expected), and it would be nice to somehow\n> be able to work on a smaller set of these conflicts at a time.\n\nIf the two (or at least one) branches have sufficient isolated commits\nyou can recreate the merges that could have happened, as is explained\n(for monotone) in:\n\nhttp://www.venge.net/mtn-wiki/ZipperMerge\n\nAnother option is to rebase one branch onto the other.\n\nEven another option is to merge the two branches but use the rebased\ntree to resolve the conflicts.\n\nThey are not for parallel merge resolution, but at least you can do\nthem incrementally.\n\nHTH,\nSanti\n"},{"id":"91042","messageId":"20080918162507.GA878@linode.davidb.org","threadId":"15574","inReplyTo":"adf1fd3d0809180855l42af4fb6l67275daef0d2a529@mail.gmail.com","subject":"Re: Help breaking up a large merge.","fromName":"David Brown","fromEmail":"git@davidb.org","sentAt":"2008-09-18T16:25:07Z","receivedAt":"2008-09-18T16:25:07Z","isPatch":false,"sender":{"key":"git@davidb.org","avatar":"https://gravatar.com/avatar/94c86a2938470a74c2eac5e2b69afc0871f79a660295c02219597aba8cb101c1?d=mp&s=160"},"body":"On Thu, Sep 18, 2008 at 05:55:34PM +0200, Santi Béjar wrote:\n\n>If the two (or at least one) branches have sufficient isolated commits\n>you can recreate the merges that could have happened, as is explained\n>(for monotone) in:\n>\n>http://www.venge.net/mtn-wiki/ZipperMerge\n>\n>Another option is to rebase one branch onto the other.\n\nEither of these is likely to result in more work.  Both branches have\nintermediate results, and there has been some communication between\nthe developers of each branch, so some things are closer at the two\ntips than they would be at intermediate stages.\n\nI started with this approach, and started realizing that I was\nresolving similar conflicts repeatedly (not the same, or rerere could\nhave helped).\n\nBasically, I'm looking for a way to break the merge effort up by\ngroups of files/directories.\n\nThanks,\nDavid\n"},{"id":"91046","messageId":"48D284BE.5040107@viscovery.net","threadId":"15574","inReplyTo":"20080918152154.GA27019@linode.davidb.org","subject":"Re: Help breaking up a large merge.","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2008-09-18T16:41:34Z","receivedAt":"2008-09-18T16:41:34Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"David Brown schrieb:\n> Say we have a tree that we've been working on for a few months.  An\n> outside vendor has also been working on the same tree during this\n> time, and we need to merge with their work.\n> \n> The difficulty I'm having is that there are a lot of conflicts\n> resulting from the merge (expected), and it would be nice to somehow\n> be able to work on a smaller set of these conflicts at a time.\n> \n> Some of the conflicts are caused by a single change in the other tree.\n> This is easy to cherry-pick into my tree, resolve, and then test those\n> changes independently.\n> \n> But other conflicts are caused by groups of commits that are\n> interleaved with others.\n\nIn a similar situation I was thinking about this approach:\n\n1. Do the merge.\n2. Resolve conflicts in an area that can be tested in isolation.\n3. Undo all other changes that the merge brought in.\n4. Commit.\n5. Install a graft that removes the second parent of the merge commit.\n6. Rinse and repeat.\n7. Finally, remove the grafts, and perhaps collapse the merge commits.\n\nI didn't test this, yet.\n\nHmm, thinking a bit more about this, 1 and 5 can probably be replaced by a\nmere 'git merge --squash'.\n\n-- Hannes\n"},{"id":"91057","messageId":"32541b130809181040p4785f877s7502c578e46745d8@mail.gmail.com","threadId":"15574","inReplyTo":"20080918152154.GA27019@linode.davidb.org","subject":"Re: Help breaking up a large merge.","fromName":"Avery Pennarun","fromEmail":"apenwarr@gmail.com","sentAt":"2008-09-18T17:40:55Z","receivedAt":"2008-09-18T17:40:55Z","isPatch":false,"sender":{"key":"apenwarr@gmail.com","avatar":"https://avatars.githubusercontent.com/u/20592?v=4"},"body":"On Thu, Sep 18, 2008 at 11:21 AM, David Brown <git@davidb.org> wrote:\n> The difficulty I'm having is that there are a lot of conflicts\n> resulting from the merge (expected), and it would be nice to somehow\n> be able to work on a smaller set of these conflicts at a time.\n>\n> Some of the conflicts are caused by a single change in the other tree.\n> This is easy to cherry-pick into my tree, resolve, and then test those\n> changes independently.\n\nI've had the same sort of problem at work and I've gone through\nseveral iterations trying to solve a problem.  The short version is\nthat all the solutions proposed here so far, plus some other ones I\nthought of, don't seem to cut down the work for me :)\n\nBut here's one that has helped quite a bit, assuming that breaking up\nthe merge by *files* makes sense.\n\n...\n\nLet's say you have two branches, A and B, derived from a base X.  We\nwant to merge the branch with fewer changes on top of the branch with\nmore changes, because it'll be less work to divide up :)  Let's assume\nthe branch with fewer changes is A.\n\n1) Generate a giant patch file using 'git diff X..A'.  Call the patch P.\n\n2) Using an editor, divide up the patch by files/subdirs based on how\nyou want to subdivide the work.  Or alternatively, do that with 'git\ndiff' itself, but beware of accidentally forgetting to ask for some\nfiles if you do it that way.  Call these n individual patches P1..Pn.\n\n3) Create new branches called A1..An, copied directly from X.\n\n4) Apply each patch P1..Pn to each branch A1..An.  (They will all\napply cleanly, because they are all patches against X in the first\nplace.)\n\n5) Create new branches called B1..Bn, copied directly from *B*.\n\n6) 'git merge' A1 into B1, A2 into B2, and so on.  Resolve the conflicts.\n\n7) Create a new branch, TEST, copied from B.  Do an octopus merge from\nB1..Bn.  There will be no conflicts, because those branches all make\nmutually exclusive changes, and they're all based on B.  You now have\na combined branch containing A+B, but the history from A is missing.\n\n8) Create a new patch, PFINAL, using 'git diff B..TEST'.  This is the\ncomplete set of changes to turn B into A+B.\n\n9) Checkout B.  'git merge A'; there will be conflicts.  'git checkout\nHEAD .' to go back to B's files. Patch in PFINAL, and commit.\n\nNow you have a single merge commit with all the changes, and the\nhistory will be correct.\n\n10) Optional: 'git merge B1..Bn' so that you don't lose the history of\nthe individual sub-merges (you might want to look at them later or use\nthem for blame purposes).  There shouldn't be any conflicts, as the\nchanges in those branches are identical to the changes you just\ncommitted, and git will discard them in the extra merge.\n\n10b) Optional advanced-only trick: amend the main commit so that it\nlooks like an octopus merge of B, A, and B1..Bn, instead of having a\nseparate fake merge commit.\n\nNote that this also helps a lot (for me) even if it's just a single\nperson doing the merge: I like to do the library changes first, get\nall the library unit tests passing, then move up to bigger and bigger\ncomponents.\n\nHope this helps.\n\nHave fun,\n\nAvery\n"},{"id":"91058","messageId":"20080918174705.GA8055@linode.davidb.org","threadId":"15574","inReplyTo":"32541b130809181040p4785f877s7502c578e46745d8@mail.gmail.com","subject":"Re: Help breaking up a large merge.","fromName":"David Brown","fromEmail":"git@davidb.org","sentAt":"2008-09-18T17:47:05Z","receivedAt":"2008-09-18T17:47:05Z","isPatch":false,"sender":{"key":"git@davidb.org","avatar":"https://gravatar.com/avatar/94c86a2938470a74c2eac5e2b69afc0871f79a660295c02219597aba8cb101c1?d=mp&s=160"},"body":"On Thu, Sep 18, 2008 at 01:40:55PM -0400, Avery Pennarun wrote:\n\n>1) Generate a giant patch file using 'git diff X..A'.  Call the patch P.\n>\n>2) Using an editor, divide up the patch by files/subdirs based on how\n>you want to subdivide the work.  Or alternatively, do that with 'git\n>diff' itself, but beware of accidentally forgetting to ask for some\n>files if you do it that way.  Call these n individual patches P1..Pn.\n\nThe is fairly close to the approach I've been taking, but somehow I\ndidn't think of using the output of diff itself and hacking that up.\nI like this because it makes it easier to not forget some files.\n\nIt is likely there will be makefiles to cleanup and such, but\notherwise I like this idea.\n\nThanks,\nDavid\n"}]}