{"thread":{"id":"28378","subject":"Okay to invoke merge-recursive with an empty workdir?","startedAt":"2011-09-13T03:13:37Z","lastAt":"2011-09-13T03:59:27Z","messageCount":4,"participants":["Jay Soffian","Jeff King","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"175380","messageId":"CAG+J_Dyz-aeLYn43ARTG4GJz0+zRw_RyDr80bmPCayd9BjzCwg@mail.gmail.com","threadId":"28378","inReplyTo":null,"subject":"Okay to invoke merge-recursive with an empty workdir?","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2011-09-13T03:13:37Z","receivedAt":"2011-09-13T03:13:37Z","isPatch":false,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"I have an unattended script which performs automated merges into\nseveral destination branches.\n\nAs the repo is fairly large, I'd like not to have to checkout each\ndestination branch, nor have multiple workdirs.\n\nSo my approach is to create a temporary, empty, workdir, using\nsymlinks to point to the parent repo per git new-workdir.\n\nI then invoke merge-recursive directly inside the temporary workdir.\n\nThe question is whether this is safe to do, or whether merge-recursive\nexpects a fully populated working tree that matches the index. My easy\ntest cases seem to work correctly, but I'm concerned that I sometimes\nget:\n\nSkipped /some/file (merged same as existing)\nerror: addinfo_cache failed for path '/some/file'\nSkipped some/other_file (merged same as existing)\nerror: addinfo_cache failed for path 'some/other_file'\n\nWhich seems to be from this code in merge-recursive.cc:\n\n\tif (mfi.clean && !df_conflict_remains &&\n\t    sha_eq(mfi.sha, a_sha) && mfi.mode == a_mode) {\n\t\tint path_renamed_outside_HEAD;\n\t\toutput(o, 3, \"Skipped %s (merged same as existing)\", path);\n\t\t/*\n\t\t * The content merge resulted in the same file contents we\n\t\t * already had.  We can return early if those file contents\n\t\t * are recorded at the correct path (which may not be true\n\t\t * if the merge involves a rename).\n\t\t */\n\t\tpath_renamed_outside_HEAD = !path2 || !strcmp(path, path2);\n\t\tif (!path_renamed_outside_HEAD) {\n\t\t\tadd_cacheinfo(mfi.mode, mfi.sha, path,\n\t\t\t\t      0 /*stage*/, 1 /*refresh*/, 0 /*options*/);\n\t\t\treturn mfi.clean;\n\t\t}\n\n(Peff, hope you don't mind me cc'ing you directly. I seem to recall\nyou're saying github is doing something like this but I couldn't find\nthat email.)\n\nj.\n"},{"id":"175381","messageId":"20110913032900.GA3296@sigill.intra.peff.net","threadId":"28378","inReplyTo":"CAG+J_Dyz-aeLYn43ARTG4GJz0+zRw_RyDr80bmPCayd9BjzCwg@mail.gmail.com","subject":"Re: Okay to invoke merge-recursive with an empty workdir?","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-09-13T03:29:00Z","receivedAt":"2011-09-13T03:29:00Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Sep 12, 2011 at 11:13:37PM -0400, Jay Soffian wrote:\n\n> So my approach is to create a temporary, empty, workdir, using\n> symlinks to point to the parent repo per git new-workdir.\n> \n> I then invoke merge-recursive directly inside the temporary workdir.\n> \n> The question is whether this is safe to do, or whether merge-recursive\n> expects a fully populated working tree that matches the index. My easy\n> test cases seem to work correctly, but I'm concerned that I sometimes\n> get:\n\nI'm not sure if we were ever using merge-recursive like that. Especially\nwith Elijah's latest patches to handle worktree dirtiness better, I\nwouldn't be surprised if it has issues.\n\nWhat we do now at GitHub is something like:\n\n  export GIT_WORK_TREE=/some/tmpdir\n  export GIT_INDEX_FILE=/some/tmpfile\n  git read-tree -i -m --aggressive $merge_base $us $them\n  git merge-index git-merge-one-file -a\n\nI also have a patch to do the content-level merge in read-tree without\ntouching the filesystem at all. But we're not using it yet, and I should\nprobably write more tests for it. You can see it at:\n\n  git://github.com/peff/git.git jk/read-tree-content-merge\n\nIt should produce the same results as the snippet above, but faster.\nBoth of those will obviously not handle renames or do recursive merges\nlike merge-recursive, of course.\n\n-Peff\n"},{"id":"175382","messageId":"7v4o0h14gv.fsf@alter.siamese.dyndns.org","threadId":"28378","inReplyTo":"20110913032900.GA3296@sigill.intra.peff.net","subject":"Re: Okay to invoke merge-recursive with an empty workdir?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-09-13T03:55:12Z","receivedAt":"2011-09-13T03:55:12Z","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> I'm not sure if we were ever using merge-recursive like that. Especially\n> with Elijah's latest patches to handle worktree dirtiness better, I\n> wouldn't be surprised if it has issues.\n\nI am parsing the above as \"seeing the need for such an extensive fix-up,\nit is not surprising if the base code is broken\", and I have to agree.\n\nIn principle, \"git merge\" should be usable in an empty working tree in the\nsense that with correctly populated index the absense of the working tree\nfile is _meant_ to be treated the same as having the file unchanged from\nthe index and the HEAD version, but I suspect that \"merge-recursive\" is\npretty much broken with that regard.\n\nI have much more faith in \"git merge -s resolve\" performing correctly.\n"},{"id":"175384","messageId":"20110913035927.GB4828@sigill.intra.peff.net","threadId":"28378","inReplyTo":"7v4o0h14gv.fsf@alter.siamese.dyndns.org","subject":"Re: Okay to invoke merge-recursive with an empty workdir?","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-09-13T03:59:27Z","receivedAt":"2011-09-13T03:59:27Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Sep 12, 2011 at 08:55:12PM -0700, Junio C Hamano wrote:\n\n> Jeff King <peff@peff.net> writes:\n> \n> > I'm not sure if we were ever using merge-recursive like that. Especially\n> > with Elijah's latest patches to handle worktree dirtiness better, I\n> > wouldn't be surprised if it has issues.\n> \n> I am parsing the above as \"seeing the need for such an extensive fix-up,\n> it is not surprising if the base code is broken\", and I have to agree.\n\nWell, both. I assume that merge-recursive now cares more than ever about\nwhat is in the working tree, because I seem to recall Elijah handling\nsome cases with untracked files. And also, his patches have given me no\nfaith whatsoever in the quality of the underlying code. :)\n\n> In principle, \"git merge\" should be usable in an empty working tree in the\n> sense that with correctly populated index the absense of the working tree\n> file is _meant_ to be treated the same as having the file unchanged from\n> the index and the HEAD version, but I suspect that \"merge-recursive\" is\n> pretty much broken with that regard.\n> \n> I have much more faith in \"git merge -s resolve\" performing correctly.\n\nAgreed, though I haven't tried it.\n\n-Peff\n"}]}