{"thread":{"id":"26754","subject":"Sharing a massive distributed merge","startedAt":"2011-03-16T20:12:46Z","lastAt":"2011-03-24T03:03:40Z","messageCount":17,"participants":["Joshua Jensen","Jay Soffian","Jeff King","Victor Engmark","Alex Riesen","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"163504","messageId":"4D8119BE.2090208@workspacewhiz.com","threadId":"26754","inReplyTo":null,"subject":"Sharing a massive distributed merge","fromName":"Joshua Jensen","fromEmail":"jjensen@workspacewhiz.com","sentAt":"2011-03-16T20:12:46Z","receivedAt":"2011-03-16T20:12:46Z","isPatch":false,"sender":{"key":"jjensen@workspacewhiz.com","avatar":"https://avatars.githubusercontent.com/u/111687?v=4"},"body":"We have two codelines that diverged quite a while back, and we are now \nbringing them back together.  More than 800 files are in conflict, but \nit is very possible that the automatic non-conflicting merge is not \ncorrecting.  This means thousands of files need to be examined.\n\nGit doesn't support distribution of a merge (although that would be \nextraordinarily cool), so the next best thing seemed to be force adding \nall files with conflict markers and then committing the merge.  We then \npublish the conflicting branch and have each person fix their files.  \nGiven that the conflict markers are already in place, they can't use \ntheir favorite graphical merge tool.\n\nWhat I want to be able to do is have each person perform the merge \nlocally, stage only the files they care about in that session, reset all \nother files, and commit as a regular commit, not a merge commit.  The \nuser can take advantage of whatever tools they want in the in progress \nmerge.  When everyone has finished this process, we run git merge and \nkeep our local changes.\n\nI have had no success in doing the above.  Is there a fancy way to pull \nthis off with Git?\n\nThanks.\n\nJosh\n"},{"id":"163527","messageId":"AANLkTim0TL5X8rKoBceK3nLA4JrtuftqkJDkRi0Lok0A@mail.gmail.com","threadId":"26754","inReplyTo":"4D8119BE.2090208@workspacewhiz.com","subject":"Re: Sharing a massive distributed merge","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2011-03-17T05:21:19Z","receivedAt":"2011-03-17T05:21:19Z","isPatch":false,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Wed, Mar 16, 2011 at 4:12 PM, Joshua Jensen\n<jjensen@workspacewhiz.com> wrote:\n> We have two codelines that diverged quite a while back, and we are now\n> bringing them back together.  More than 800 files are in conflict, but it is\n> very possible that the automatic non-conflicting merge is not correcting.\n>  This means thousands of files need to be examined.\n\nHave you considered breaking this up into multiple merges, so that\neach merge deals with only a subset of the conflicts? This may mean\nmore work overall, but makes reviewing each individual merge much more\ntenable.\n\nIOW, given a history like:\n\n a--b--c--d--e...z\n  \\\n   1--2--3--4...25\n\nInstead of trying to merge z into 25, first merge b, then c, etc. I'd\ntry a divide and conquer approach - merge half way back to the common\nancestor, it that's too big, go half way back again, etc.\n\nThis obviously doesn't parallelize the effort.\n\n> Git doesn't support distribution of a merge (although that would be\n> extraordinarily cool), so the next best thing seemed to be force adding all\n> files with conflict markers and then committing the merge.  We then publish\n> the conflicting branch and have each person fix their files.  Given that the\n> conflict markers are already in place, they can't use their favorite\n> graphical merge tool.\n\nWell, this is awful, but you could do something like:\n\nfor x in conflicted_files:\n   git show :1:$x > $x.base\n   git show :3:$x > $x.theirs\n   git checkout --ours $x\n   git add $x.base $x.theirs $x\n\nCommit that, then folks can use their favorite merge tools, commit the\nresult, and remove the .base and .theirs.\n\nNotes:\n\n- I'd do all this work on its own branch. When all the files have been\nresolved, then do a real merge, but consult the branch for the\nconflict resolution, e.g. \"git merge ...; git checkout\nmerge_resolution -- .\"\n\n- See git-mergetool.sh for how to use checkout-index instead of \"show\n:<stage>:...\"\n\n- This only handles modify/modify conflicts.\n\n- You might want to use \"merge.conflictstyle diff3\" and commit that\nfile too so that there's a reference file with the conflict markers --\nI find the diff3 style very helpful in addition to GUI mergetools, for\nwhich I've not found one that does a good presentation of theirs,\nours, base, and resolved.\n\n> What I want to be able to do is have each person perform the merge locally,\n> stage only the files they care about in that session, reset all other files,\n> and commit as a regular commit, not a merge commit.  The user can take\n> advantage of whatever tools they want in the in progress merge.  When\n> everyone has finished this process, we run git merge and keep our local\n> changes.\n\n$ git merge --squash other_branch\n# resolve foo\n$ git commit -m \"resolved foo\" -- foo\n$ git reset --hard\n\nThough I think the \"awful\" solution above might prove less error prone\nand do a better job of keeping track of the remaining work.\n\nj.\n"},{"id":"163529","messageId":"20110317063816.GD11931@sigill.intra.peff.net","threadId":"26754","inReplyTo":"AANLkTim0TL5X8rKoBceK3nLA4JrtuftqkJDkRi0Lok0A@mail.gmail.com","subject":"Re: Sharing a massive distributed merge","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-03-17T06:38:16Z","receivedAt":"2011-03-17T06:38:16Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Mar 17, 2011 at 01:21:19AM -0400, Jay Soffian wrote:\n\n> > Git doesn't support distribution of a merge (although that would be\n> > extraordinarily cool), so the next best thing seemed to be force adding all\n> > files with conflict markers and then committing the merge.  We then publish\n> > the conflicting branch and have each person fix their files.  Given that the\n> > conflict markers are already in place, they can't use their favorite\n> > graphical merge tool.\n> \n> Well, this is awful, but you could do something like:\n> \n> for x in conflicted_files:\n>    git show :1:$x > $x.base\n>    git show :3:$x > $x.theirs\n>    git checkout --ours $x\n>    git add $x.base $x.theirs $x\n> \n> Commit that, then folks can use their favorite merge tools, commit the\n> result, and remove the .base and .theirs.\n\nI don't think you need to do anything so drastic. You can just have\neverybody do the partial merge, commit, and then push their result.  And\nthen as you suggest below, one person does the real merge, uses checkout\nto install the desired result state from each person's partial tree, and\nthen everybody throws away their partial merges.\n\nThe trick is that each person will resolve some conflicts and commit,\nbut you need to know which ones they resolved. They can't leave things\nunmerged in the final commit. So they would have to provide such a list\nto you; one way is in the commit message[1].\n\nSo let's say you have three devs, Alice, Bob, and Charlie, and one\nintegrator, Matt, who will do the merge. Each of the developers does:\n\n  git checkout -b partial-merge\n  git merge old-topic\n  git mergetool ;# or manually resolve and git add\n\nEventually they get tired of the conflicts and give up. So they record\nthe list of resolved paths, either manually or with something like[2]:\n\n  {\n    echo 'partial merge result'\n    echo\n\n    git status --porcelain | perl -ne '\n      next if /^U|\\?/;\n      s/^\\S+\\s+//;\n      print;\n    '\n\n  } >msg\n\nAnd then they stage the rest of it (knowing it will be ignored by Matt)\nand commit:\n\n  git add -u\n  git commit -F msg\n  git push wherever partial-merge\n\nThen Matt does the actual merge:\n\n  git merge old-topic\n\nwhich of course results in lots of conflicts. So he pulls resolved\nversions from each person's tree:\n\n  for i in alice bob charlie; do\n    git fetch $i\n    git checkout $i/partial-merge -- \\\n      `git log -1 --format:%b $i/partial-merge`\n  done\n\nAnd then fixes up whatever's left manually or with git-mergetool, and\ncommits the end result.\n\nTake all of my scripting there as illustrative of the concept, but not\nnecessarily a good idea. In particular, it doesn't handle quoting of\nfilenames at all, and it probably doesn't handle files whose resolution\nwas to be deleted (since the checkout will fail).\n\n-Peff\n\n[1] I also considered that instead of noting the resolved files in the\ncommit message, the developers could just remove anything they didn't\nresolve. After all, their tree is going to be thrown away eventually.\nThen Matt could just script around \"git ls-tree\" to pull their files\nout. The downside is that there is no way for the developers to say \"the\nresolution is to delete this file\", since it just looks like something\nthey didn't resolve.\n\n[2] It really seems like the right command to get the list of resolved\nfiles would be \"git diff-index\" with either a diff-filter, or grepping\nthe output of --name-status. But I couldn't convince it to show me\nunmerged files; the unmerged entries always just appeared as\nmodifications (actually, deletions in --raw), which made them\nindistinguishable from modified resolutions.\n"},{"id":"163534","messageId":"AANLkTikdXCo_3hGZSaW3+9x6gQ2_B3A=scWN-f3gMSY4@mail.gmail.com","threadId":"26754","inReplyTo":"20110317063816.GD11931@sigill.intra.peff.net","subject":"Re: Sharing a massive distributed merge","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2011-03-17T07:04:14Z","receivedAt":"2011-03-17T07:04:14Z","isPatch":false,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Thu, Mar 17, 2011 at 2:38 AM, Jeff King <peff@peff.net> wrote:\n> [2] It really seems like the right command to get the list of resolved\n> files would be \"git diff-index\" with either a diff-filter, or grepping\n> the output of --name-status. But I couldn't convince it to show me\n> unmerged files; the unmerged entries always just appeared as\n> modifications (actually, deletions in --raw), which made them\n> indistinguishable from modified resolutions.\n\nI use this alias for getting unmerged files:\n\n$ git help unmerged\n`git unmerged' is aliased to `!git ls-files --unmerged | cut -f2 | uniq'\n\nj.\n"},{"id":"163536","messageId":"20110317073053.GI11931@sigill.intra.peff.net","threadId":"26754","inReplyTo":"AANLkTikdXCo_3hGZSaW3+9x6gQ2_B3A=scWN-f3gMSY4@mail.gmail.com","subject":"Re: Sharing a massive distributed merge","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-03-17T07:30:53Z","receivedAt":"2011-03-17T07:30:53Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Mar 17, 2011 at 03:04:14AM -0400, Jay Soffian wrote:\n\n> On Thu, Mar 17, 2011 at 2:38 AM, Jeff King <peff@peff.net> wrote:\n> > [2] It really seems like the right command to get the list of resolved\n> > files would be \"git diff-index\" with either a diff-filter, or grepping\n> > the output of --name-status. But I couldn't convince it to show me\n> > unmerged files; the unmerged entries always just appeared as\n> > modifications (actually, deletions in --raw), which made them\n> > indistinguishable from modified resolutions.\n> \n> I use this alias for getting unmerged files:\n> \n> $ git help unmerged\n> `git unmerged' is aliased to `!git ls-files --unmerged | cut -f2 | uniq'\n\nYeah, that would work. Though we really want the list of _resolved_\nfiles. So you'd have to do something like:\n\n  git ls-files --unmerged | cut -f2 | uniq >unmerged\n  git diff-index HEAD >all\n  comm -23 all unmerged\n\nwhich is why I was hoping to do it with diff-index in the first place.\n\n-Peff\n"},{"id":"163538","messageId":"4D81BD9E.1050601@terreactive.ch","threadId":"26754","inReplyTo":"10061287.5697.1300343903667.JavaMail.trustmail@mail1.terreactive.ch","subject":"Where do all the tips go? (Was: Re: Sharing a massive distributed merge)","fromName":"Victor Engmark","fromEmail":"victor.engmark@terreactive.ch","sentAt":"2011-03-17T07:51:58Z","receivedAt":"2011-03-17T07:51:58Z","isPatch":false,"sender":{"key":"victor.engmark@terreactive.ch","avatar":null},"body":"On 03/17/2011 07:38 AM, Jeff King wrote:\n> On Thu, Mar 17, 2011 at 01:21:19AM -0400, Jay Soffian wrote:\n> \n>>> Git doesn't support distribution of a merge (although that would be\n>>> extraordinarily cool), so the next best thing seemed to be force adding all\n>>> files with conflict markers and then committing the merge.  We then publish\n>>> the conflicting branch and have each person fix their files.  Given that the\n>>> conflict markers are already in place, they can't use their favorite\n>>> graphical merge tool.\n>>\n>> Well, this is awful, but you could do something like:\n>>\n>> for x in conflicted_files:\n>>    git show :1:$x > $x.base\n>>    git show :3:$x > $x.theirs\n>>    git checkout --ours $x\n>>    git add $x.base $x.theirs $x\n>>\n>> Commit that, then folks can use their favorite merge tools, commit the\n>> result, and remove the .base and .theirs.\n> \n> I don't think you need to do anything so drastic. You can just have\n> everybody do the partial merge, commit, and then push their result.  And\n> then as you suggest below, one person does the real merge, uses checkout\n> to install the desired result state from each person's partial tree, and\n> then everybody throws away their partial merges.\n> \n> The trick is that each person will resolve some conflicts and commit,\n> but you need to know which ones they resolved. They can't leave things\n> unmerged in the final commit. So they would have to provide such a list\n> to you; one way is in the commit message[1].\n> \n> So let's say you have three devs, Alice, Bob, and Charlie, and one\n> integrator, Matt, who will do the merge. Each of the developers does:\n> \n>   git checkout -b partial-merge\n>   git merge old-topic\n>   git mergetool ;# or manually resolve and git add\n> \n> Eventually they get tired of the conflicts and give up. So they record\n> the list of resolved paths, either manually or with something like[2]:\n> \n>   {\n>     echo 'partial merge result'\n>     echo\n> \n>     git status --porcelain | perl -ne '\n>       next if /^U|\\?/;\n>       s/^\\S+\\s+//;\n>       print;\n>     '\n> \n>   } >msg\n> \n> And then they stage the rest of it (knowing it will be ignored by Matt)\n> and commit:\n> \n>   git add -u\n>   git commit -F msg\n>   git push wherever partial-merge\n> \n> Then Matt does the actual merge:\n> \n>   git merge old-topic\n> \n> which of course results in lots of conflicts. So he pulls resolved\n> versions from each person's tree:\n> \n>   for i in alice bob charlie; do\n>     git fetch $i\n>     git checkout $i/partial-merge -- \\\n>       `git log -1 --format:%b $i/partial-merge`\n>   done\n> \n> And then fixes up whatever's left manually or with git-mergetool, and\n> commits the end result.\n> \n> Take all of my scripting there as illustrative of the concept, but not\n> necessarily a good idea. In particular, it doesn't handle quoting of\n> filenames at all, and it probably doesn't handle files whose resolution\n> was to be deleted (since the checkout will fail).\n\nThis discussion is great! Is there some place where this sort of a thing\nusually ends up, such as a wiki or the Git Community Book\n<http://book.git-scm.com/>?\n\nCheers,\n-- \nVictor Engmark\n"},{"id":"163539","messageId":"20110317080117.GA16202@sigill.intra.peff.net","threadId":"26754","inReplyTo":"4D81BD9E.1050601@terreactive.ch","subject":"Re: Where do all the tips go? (Was: Re: Sharing a massive distributed merge)","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-03-17T08:01:17Z","receivedAt":"2011-03-17T08:01:17Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Mar 17, 2011 at 08:51:58AM +0100, Victor Engmark wrote:\n\n> > Take all of my scripting there as illustrative of the concept, but not\n> > necessarily a good idea. In particular, it doesn't handle quoting of\n> > filenames at all, and it probably doesn't handle files whose resolution\n> > was to be deleted (since the checkout will fail).\n> \n> This discussion is great! Is there some place where this sort of a thing\n> usually ends up, such as a wiki or the Git Community Book\n> <http://book.git-scm.com/>?\n\nThere's an FAQ section on the wiki:\n\n  https://git.wiki.kernel.org/index.php/GitFaq\n\nthough I am not sure this is frequently asked. The Git Community Book\nseems pretty inactive these days. The last work on it is about 2 years\nold:\n\n  https://github.com/schacon/gitbook\n\nThese days Pro Git is freely available and seems much more active:\n\n  https://github.com/progit/progit\n\nI know Scott is collecting random advanced topics like this for an\neventual second edition. Maybe this topic would be of interest.\n\n-Peff\n"},{"id":"163543","messageId":"AANLkTimTKbKWmf80u-kgnvQ2gT8hx2KTm6HGbWejt3eg@mail.gmail.com","threadId":"26754","inReplyTo":"20110317063816.GD11931@sigill.intra.peff.net","subject":"Re: Sharing a massive distributed merge","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2011-03-17T08:53:21Z","receivedAt":"2011-03-17T08:53:21Z","isPatch":false,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"On Thu, Mar 17, 2011 at 07:38, Jeff King <peff@peff.net> wrote:\n> I don't think you need to do anything so drastic. You can just have\n> everybody do the partial merge, commit, and then push their result.  And\n> then as you suggest below, one person does the real merge, uses checkout\n> to install the desired result state from each person's partial tree, and\n> then everybody throws away their partial merges.\n>\n> The trick is that each person will resolve some conflicts and commit,\n> but you need to know which ones they resolved. They can't leave things\n> unmerged in the final commit. So they would have to provide such a list\n> to you; one way is in the commit message[1].\n>\n> So let's say you have three devs, Alice, Bob, and Charlie, and one\n> integrator, Matt, who will do the merge. Each of the developers does:\n>\n>  git checkout -b partial-merge\n>  git merge old-topic\n>  git mergetool ;# or manually resolve and git add\n>\n> Eventually they get tired of the conflicts and give up. So they record\n> the list of resolved paths, either manually or with something like[2]:\n>\n...\n>\n> And then they stage the rest of it (knowing it will be ignored by Matt)\n> and commit:\n>\n\nWhat if they just revert the rest? Reset the files to their states before\nmerge. Than Matt can just collect the partial merges with a merge on\nhis side and take care of the conflicts left, which should be fewer.\n"},{"id":"163560","messageId":"AANLkTi=25=99Gh9hGUxEuvB9Xvv=f8uJxThaMxaAQKbq@mail.gmail.com","threadId":"26754","inReplyTo":"AANLkTimTKbKWmf80u-kgnvQ2gT8hx2KTm6HGbWejt3eg@mail.gmail.com","subject":"Re: Sharing a massive distributed merge","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2011-03-17T14:10:36Z","receivedAt":"2011-03-17T14:10:36Z","isPatch":false,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Thu, Mar 17, 2011 at 4:53 AM, Alex Riesen <raa.lkml@gmail.com> wrote:\n> What if they just revert the rest? Reset the files to their states before\n> merge.\n\nThat's the same as checkout --ours which is sometimes a valid\nresolution for a file. So I think \"I resolved this file\" needs to be\nrecorded either way.\n\nj.\n"},{"id":"163563","messageId":"AANLkTikfp_d00zrtU8kuvyUk81gGMkOXEVDNXr-hRhBU@mail.gmail.com","threadId":"26754","inReplyTo":"AANLkTi=25=99Gh9hGUxEuvB9Xvv=f8uJxThaMxaAQKbq@mail.gmail.com","subject":"Re: Sharing a massive distributed merge","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2011-03-17T14:54:44Z","receivedAt":"2011-03-17T14:54:44Z","isPatch":false,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"On Thu, Mar 17, 2011 at 15:10, Jay Soffian <jaysoffian@gmail.com> wrote:\n> On Thu, Mar 17, 2011 at 4:53 AM, Alex Riesen <raa.lkml@gmail.com> wrote:\n>> What if they just revert the rest? Reset the files to their states before\n>> merge.\n>\n> That's the same as checkout --ours which is sometimes a valid\n> resolution for a file. So I think \"I resolved this file\" needs to be\n> recorded either way.\n\nBut it is recorded: the file is different now!\n"},{"id":"163568","messageId":"AANLkTinQYjq=NiHK6MK0tA5AEE7=NCg8kthJT9Xz=xNk@mail.gmail.com","threadId":"26754","inReplyTo":"AANLkTikfp_d00zrtU8kuvyUk81gGMkOXEVDNXr-hRhBU@mail.gmail.com","subject":"Re: Sharing a massive distributed merge","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2011-03-17T17:58:20Z","receivedAt":"2011-03-17T17:58:20Z","isPatch":false,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Thu, Mar 17, 2011 at 10:54 AM, Alex Riesen <raa.lkml@gmail.com> wrote:\n> On Thu, Mar 17, 2011 at 15:10, Jay Soffian <jaysoffian@gmail.com> wrote:\n>> On Thu, Mar 17, 2011 at 4:53 AM, Alex Riesen <raa.lkml@gmail.com> wrote:\n>>> What if they just revert the rest? Reset the files to their states before\n>>> merge.\n>>\n>> That's the same as checkout --ours which is sometimes a valid\n>> resolution for a file. So I think \"I resolved this file\" needs to be\n>> recorded either way.\n>\n> But it is recorded: the file is different now!\n\nLet's say we have:\n\n  a---b---c\n   \\\n    d---e\n\n$ git checkout c\n$ git merge e  # files \"foo\" and \"bar\" conflict\n$ git checkout --ours foo  # correct resolution for foo\n$ git checkout HEAD bar    # \"revert\" bar to its pre-merge state\n$ git add foo\n$ git commit\n\nIn the merge commit, both \"foo\" and \"bar\" are identical to their\npre-merge state. There's no effective difference between the \"checkout\n--ours\" and \"reset the files to their states before the merge\".\n\nSo again, how do you tell the difference here?\n\nj.\n"},{"id":"163574","messageId":"AANLkTi=Fnacc9JamGdOEYhHY8PJgaidSLmif_z5Qdfp0@mail.gmail.com","threadId":"26754","inReplyTo":"AANLkTinQYjq=NiHK6MK0tA5AEE7=NCg8kthJT9Xz=xNk@mail.gmail.com","subject":"Re: Sharing a massive distributed merge","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2011-03-17T18:48:54Z","receivedAt":"2011-03-17T18:48:54Z","isPatch":false,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"On Thu, Mar 17, 2011 at 18:58, Jay Soffian <jaysoffian@gmail.com> wrote:\n> On Thu, Mar 17, 2011 at 10:54 AM, Alex Riesen <raa.lkml@gmail.com> wrote:\n>> On Thu, Mar 17, 2011 at 15:10, Jay Soffian <jaysoffian@gmail.com> wrote:\n>>> On Thu, Mar 17, 2011 at 4:53 AM, Alex Riesen <raa.lkml@gmail.com> wrote:\n>>>> What if they just revert the rest? Reset the files to their states before\n>>>> merge.\n>>>\n>>> That's the same as checkout --ours which is sometimes a valid\n>>> resolution for a file. So I think \"I resolved this file\" needs to be\n>>> recorded either way.\n>>\n>> But it is recorded: the file is different now!\n>\n> Let's say we have:\n>\n>  a---b---c\n>   \\\n>    d---e\n>\n> $ git checkout c\n> $ git merge e  # files \"foo\" and \"bar\" conflict\n> $ git checkout --ours foo  # correct resolution for foo\n\nI doubt that'll be a correct resolution. Someone have to look\nat the conflict markers, right?\n\n> $ git checkout HEAD bar    # \"revert\" bar to its pre-merge state\n> $ git add foo\n> $ git commit\n>\n> In the merge commit, both \"foo\" and \"bar\" are identical to their\n> pre-merge state. There's no effective difference between the \"checkout\n> --ours\" and \"reset the files to their states before the merge\".\n>\n> So again, how do you tell the difference here?\n>\n\nThe difference may be simple (git diff --name-status c^..),\nit just does not help. The merge commit will record the\nbranches as merged and an attempt by the maintainer to merge\nthis partial merge commit will just fast-forward. So it was\na stupid idea either way.\n\nHow about not to record the merge as a merge commit, but\njust resolve as much as possible, commit _only_ what was\nresolved, and revert everything else. Including files merged\ncleanly, as the last merge by maintainer will have to clean\nmerge them anyway. And of course, commit as normal:\n\n  $ git merge --squash --no-commit e\n\nThe maintainer will have to collect the branches with resolved\nconflicts, and fix up the conflicts left.\n\nCould be less work, given good coordination of who resolves what...\n"},{"id":"163575","messageId":"20110317191517.GC20508@sigill.intra.peff.net","threadId":"26754","inReplyTo":"AANLkTi=Fnacc9JamGdOEYhHY8PJgaidSLmif_z5Qdfp0@mail.gmail.com","subject":"Re: Sharing a massive distributed merge","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-03-17T19:15:17Z","receivedAt":"2011-03-17T19:15:17Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Mar 17, 2011 at 07:48:54PM +0100, Alex Riesen wrote:\n\n> How about not to record the merge as a merge commit, but\n> just resolve as much as possible, commit _only_ what was\n> resolved, and revert everything else. Including files merged\n> cleanly, as the last merge by maintainer will have to clean\n> merge them anyway. And of course, commit as normal:\n\nBut that still has the same problem. You've reverted unresolved files\nback to the pre-merge state, which is the tip of one of the merged\nbranches. How does the integrator differentiate that from the case that\nyour resolution happened to take one side of a file?\n\nFor example, try this:\n\n    git init repo && cd repo\n\n    echo base >file1\n    echo base >file2\n    git add .\n    git commit -m base\n\n    echo master >>file1\n    echo master >>file2\n    git commit -a -m master\n\n    git checkout -b topic HEAD^\n    echo topic >>file1\n    echo topic >>file2\n    git commit -a -m topic\n\n    git merge master\n\n    # now we have a conflict. Both files are identically conflicted.\n    # Let's resolve one in favor of topic.\n    cat >file1 <<'EOF'\n    base\n    topic\n    EOF\n    git add file1\n\n    # Now let's mark the other as unresolved. The proposal is to revert\n    # it back to the pre-merge state.\n    git checkout HEAD -- file2\n\n    # And commit the partial result.\n    git commit -m 'partial result'\n\nIt should be easy to see that the two cases are indistinguishable: both\nfiles contain the exact same content in the reuslting partial result\n(and obviously the fact that they are identical is contrived, but the\npoint is that for any given file, you don't know which thing happened\nduring the partial merge).\n\nWhich is why I suggested deletion as an option, but that also conflicts\nwith a possible resolution (it's just a less likely one). I think every\ntree state that you could commit to mark \"this isn't resolved\" is going\nto overlap with some possible actual resolution state. So you need an\nexternal list.\n\nIt would be neat if the tree could somehow mark a bit for \"this is\nunresolved\". I guess we could shove it into a mode bit. But that seems\nlike a waste of a mode bit for this one use case that doesn't come up\nall that often, and which doesn't _need_ to represent that information\nin-tree. The commit-message solution would work perfectly fine.\n\n-Peff\n"},{"id":"163586","messageId":"AANLkTinu3_ZEfkqyVziE2Z=t-R4j_6zRiddrkXOOvAwe@mail.gmail.com","threadId":"26754","inReplyTo":"20110317191517.GC20508@sigill.intra.peff.net","subject":"Re: Sharing a massive distributed merge","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2011-03-17T19:53:04Z","receivedAt":"2011-03-17T19:53:04Z","isPatch":false,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"On Thu, Mar 17, 2011 at 20:15, Jeff King <peff@peff.net> wrote:\n> On Thu, Mar 17, 2011 at 07:48:54PM +0100, Alex Riesen wrote:\n>\n>> How about not to record the merge as a merge commit, but\n>> just resolve as much as possible, commit _only_ what was\n>> resolved, and revert everything else. Including files merged\n>> cleanly, as the last merge by maintainer will have to clean\n>> merge them anyway. And of course, commit as normal:\n>\n> But that still has the same problem. You've reverted unresolved files\n> back to the pre-merge state, which is the tip of one of the merged\n> branches. How does the integrator differentiate that from the case that\n> your resolution happened to take one side of a file?\n\nMaybe they're lucky and it just never happens? But yes, of course...\n"},{"id":"163593","messageId":"7vd3lp31tw.fsf@alter.siamese.dyndns.org","threadId":"26754","inReplyTo":"20110317191517.GC20508@sigill.intra.peff.net","subject":"Re: Sharing a massive distributed merge","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-03-17T20:54:19Z","receivedAt":"2011-03-17T20:54:19Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> It would be neat if the tree could somehow mark a bit for \"this is\n> unresolved\". I guess we could shove it into a mode bit. But that seems\n> like a waste of a mode bit for this one use case that doesn't come up\n> all that often, and which doesn't _need_ to represent that information\n> in-tree. The commit-message solution would work perfectly fine.\n\nJust adding the blob with the whole glory of <<</>>> markers would be\nbetter than recording --ours or --theirs.  Deleting might be a workaround\nthat would work better in practice as somebody already mentioned, though.\n\nI agree that message is an essential part of the communication medium to\ncoordinate this kind of workflow.  It is not like the downstream is a dumb\nmachinery that blindly grab and overlay the partial merge results that can\nonly read from tree objects and not commit messages.\n"},{"id":"163606","messageId":"20110318054934.GA7547@sigill.intra.peff.net","threadId":"26754","inReplyTo":"20110317073053.GI11931@sigill.intra.peff.net","subject":"Re: Sharing a massive distributed merge","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-03-18T05:49:34Z","receivedAt":"2011-03-18T05:49:34Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Mar 17, 2011 at 03:30:53AM -0400, Jeff King wrote:\n\n> On Thu, Mar 17, 2011 at 03:04:14AM -0400, Jay Soffian wrote:\n> \n> > On Thu, Mar 17, 2011 at 2:38 AM, Jeff King <peff@peff.net> wrote:\n> > > [2] It really seems like the right command to get the list of resolved\n> > > files would be \"git diff-index\" with either a diff-filter, or grepping\n> > > the output of --name-status. But I couldn't convince it to show me\n> > > unmerged files; the unmerged entries always just appeared as\n> > > modifications (actually, deletions in --raw), which made them\n> > > indistinguishable from modified resolutions.\n> > \n> > I use this alias for getting unmerged files:\n> > \n> > $ git help unmerged\n> > `git unmerged' is aliased to `!git ls-files --unmerged | cut -f2 | uniq'\n> \n> Yeah, that would work. Though we really want the list of _resolved_\n> files. So you'd have to do something like:\n> \n>   git ls-files --unmerged | cut -f2 | uniq >unmerged\n>   git diff-index HEAD >all\n>   comm -23 all unmerged\n> \n> which is why I was hoping to do it with diff-index in the first place.\n\nHmph. An unrelated thread just contained the answer I wanted. It's:\n\n  git diff-index --cached --name-status\n\nwhich properly produces \"U\" entries. How's that for user-friendly?\n\n-Peff\n"},{"id":"164199","messageId":"4D8AB48C.9080302@workspacewhiz.com","threadId":"26754","inReplyTo":"20110318054934.GA7547@sigill.intra.peff.net","subject":"Re: Sharing a massive distributed merge","fromName":"Joshua Jensen","fromEmail":"jjensen@workspacewhiz.com","sentAt":"2011-03-24T03:03:40Z","receivedAt":"2011-03-24T03:03:40Z","isPatch":false,"sender":{"key":"jjensen@workspacewhiz.com","avatar":"https://avatars.githubusercontent.com/u/111687?v=4"},"body":"Thank you, everyone, for all the feedback.  It still isn't clear to me \nhow we can only resolve part of a merge and easily throw away all the \nother files, but we moved forward by just committing the conflict \nmarkers and resolving from there.\n\nJosh\n"}]}