{"thread":{"id":"28412","subject":"Merging back from master but keeping a subtree","startedAt":"2011-09-17T07:49:40Z","lastAt":"2011-11-16T13:39:40Z","messageCount":3,"participants":["Steinar Bang","Jeff King"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"175683","messageId":"87y5xn8v6z.fsf@dod.no","threadId":"28412","inReplyTo":null,"subject":"Merging back from master but keeping a subtree","fromName":"Steinar Bang","fromEmail":"sb@dod.no","sentAt":"2011-09-17T07:49:40Z","receivedAt":"2011-09-17T07:49:40Z","isPatch":false,"sender":{"key":"sb@dod.no","avatar":null},"body":"I have a long lived branch that changes a directory and its\nsubdirectory, ie. \n top/middle/mydirectory\n\nNow I want to merge in an updated remoterepo/master and keep everything\nfrom that master, except for mydirectory and its subdirectory, where I\nwould like to keep everything from my branch.\n\nI tried a regular merge, and used\n git checkout --ours\n git add\nand \n git checkout --theirs\n git add\nas appropriate on all conflicts.\n\nBut the result didn't build, and the build errors don't make much sense,\nso I think they are caused by \"successful\" merges giving bad results.\n\nIs there a better way to do this?\n\nWould it be possible to unstage the already staged files and apply the\n\"checkout --ours\" and \"checkout --theirs\", and then git add on the\nchecked out files?\n\nEven that would be clumsy... I would have preferred something like\n git checkout --theirs top\n git checkout --ours top/middle/mydirectory\n git add-only-those-modified-wrt-my-branch\n\n\nThanks!\n\n- Steinar\n"},{"id":"175710","messageId":"20110918033719.GB17977@sigill.intra.peff.net","threadId":"28412","inReplyTo":"87y5xn8v6z.fsf@dod.no","subject":"Re: Merging back from master but keeping a subtree","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-09-18T03:37:19Z","receivedAt":"2011-09-18T03:37:19Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Sep 17, 2011 at 09:49:40AM +0200, Steinar Bang wrote:\n\n> I have a long lived branch that changes a directory and its\n> subdirectory, ie. \n>  top/middle/mydirectory\n> \n> Now I want to merge in an updated remoterepo/master and keep everything\n> from that master, except for mydirectory and its subdirectory, where I\n> would like to keep everything from my branch.\n\nGit should generally do that automatically, unless both sides are\nchanging mydirectory. In which case it will produce conflicts.\n\nAre you sure you really want to just throw out what the other side did\nin mydirectory?\n\n> I tried a regular merge, and used\n>  git checkout --ours\n>  git add\n> and \n>  git checkout --theirs\n>  git add\n> as appropriate on all conflicts.\n> \n> But the result didn't build, and the build errors don't make much sense,\n> so I think they are caused by \"successful\" merges giving bad results.\n\nIf git was able to auto-merge some files, then they will not be marked\nas conflicts in the index. And \"git checkout --ours\" is about looking in\nthe index for conflicted entries, and then selecting one side.\n\nI think what you want instead is to do is (assuming you really want to\nthrow out their side):\n\n  1. Start a merge between them and us:\n\n       git merge --no-commit remoterepo/master\n\n  2. Throw out whatever the merge came up with and make it look like\n     their tree:\n\n       git checkout remoterepo/master -- top\n\n  3. Now overwrite their version of mydirectory with what was in your\n     branch:\n\n       git checkout HEAD -- top/middle/mydirectory\n\n  4. Commit the resulting tree:\n\n       git commit\n\n-Peff\n"},{"id":"179588","messageId":"87aa7wrxsz.fsf@dod.no","threadId":"28412","inReplyTo":"20110918033719.GB17977@sigill.intra.peff.net","subject":"Re: Merging back from master but keeping a subtree","fromName":"Steinar Bang","fromEmail":"sb@dod.no","sentAt":"2011-11-16T13:39:40Z","receivedAt":"2011-11-16T13:39:40Z","isPatch":false,"sender":{"key":"sb@dod.no","avatar":null},"body":">>>>> Jeff King <peff@peff.net>:\n\n> Git should generally do that automatically, unless both sides are\n> changing mydirectory. In which case it will produce conflicts.\n\nI thought so too, but the end result didn't build, and I was unable to\nfigure out why.\n\n> Are you sure you really want to just throw out what the other side did\n> in mydirectory?\n\nYes, that's the only thing I'm sure about.  All changes to mydirectory\nshould come from my branch.  If there are changes necessary to make\nthings build, they are better done by me.\n\n> If git was able to auto-merge some files, then they will not be marked\n> as conflicts in the index. And \"git checkout --ours\" is about looking in\n> the index for conflicted entries, and then selecting one side.\n\n> I think what you want instead is to do is (assuming you really want to\n> throw out their side):\n\nThanks for the suggestion.  I tried following this approach, but...\n\n>   1. Start a merge between them and us:\n\n>        git merge --no-commit remoterepo/master\n\n>   2. Throw out whatever the merge came up with and make it look like\n>      their tree:\n\n...I never quite could figure out if I did the right thing here.\nIe. when throwing out what the commit came up with.\n\n>        git checkout remoterepo/master -- top\n\n>   3. Now overwrite their version of mydirectory with what was in your\n>      branch:\n\n>        git checkout HEAD -- top/middle/mydirectory\n\n>   4. Commit the resulting tree:\n\n>        git commit\n\nThe problem was that the end result didn't build, wit pretty much the\nsame obscure failures that the regular merge had.\n\nBut I eventually tried something that worked:\n 1. First create a local branch off master\n 2. Merge in mybranch with \"-s ours --no-commit\"\n 3. Checkout mydirectory from mybranch\n 4. Commit\n 5. Switch to mybranch\n 6. Merge in the new local branch, which resulted in a conflict-free\n    merge that has my changes in mydirectory and the rest of the world\n    in the rest of the working directory, and the history of mydirectory\n    looks ok\n\nThe end result built and worked.\n\nIf git had had a \"-s theirs\" strategy, I wouldn't have needed the\ntemporary branch made off master.  That need for that branch is probably\nthe most cryptic thing for people following my instructions for future\nmerges.\n\nTo sum up the commands:\n git checkout master\n git checkout -b master_nicely_merged_with_mybranch\n git merge -s ours --no-commit origin/mybranch\n git checkout origin/mybranch top/middle/mydirectory\n git commit\n git checkout mybranch\n git merge master_nicely_merged_with_mybranch\n\nThanks!\n\n\n- Steinar\n"}]}