{"thread":{"id":"53891","subject":"[BUG?] shallow-since can't handle merges","startedAt":"2020-07-21T16:06:46Z","lastAt":"2020-07-21T16:06:46Z","messageCount":1,"participants":["Jeff King"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"401807","messageId":"20200721160643.GA3288097@coredump.intra.peff.net","threadId":"53891","inReplyTo":null,"subject":"[BUG?] shallow-since can't handle merges","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2020-07-21T16:06:43Z","receivedAt":"2020-07-21T16:06:46Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"I came across an interesting case where the shallow code doesn't do do\nthe right thing. From my reading, it doesn't look like it could possibly\nwork, but I also don't understand the shallow feature very well, so here\nwe are. :)\n\nTo reproduce:\n\n  # make a copy of the \"upstream\" repo; you can also fetch directly from\n  # it, but having it locally lets you poke at both sides of the\n  # conversation\n  git clone --bare https://github.com/DefinitelyTyped/DefinitelyTyped upstream.git\n\n  # now make a local copy of a related repo\n  git clone --bare --depth=1 https://github.com/Maxim-Mazurok/DefinitelyTyped --no-single-branch repo.git\n  cd repo.git\n\n  # and then try to deepen down to this date. This is early morning on\n  # May 9 2020.\n  git remote add upstream ../upstream.git\n  git fetch upstream master --shallow-since=1589000000\n\nThe resulting history you get is cut off at May 12, even though there\nare parent commits between May 9 and May 12 that should be included.\n\nHere's what the graph in upstream.git looks like:\n\n  $ git log --all --graph --format='%cd %h' --date=iso-local\n  * 2020-07-21 13:31:19 +0000 3e7ef84b0a\n  * 2020-07-21 02:15:25 +0000 97f6a9df78\n  [...]\n  * 2020-05-12 23:57:33 +0000 9a0645f52a\n  *   2020-05-12 23:55:43 +0000 c7883f4581\n  |\\\n  | * 2020-04-28 17:17:56 +0000 a4b68cbe3a\n  * |   2020-05-12 23:50:34 +0000 9d282b0d7d\n  |\\ \\\n  | * | 2020-05-05 23:53:20 +0000 daf04e0dcb\n  | * | 2020-05-05 23:53:18 +0000 4b2129de54\n  * | | 2020-05-12 22:56:55 +0000 c599db54c9\n  * | | 2020-05-12 22:04:29 +0000 5bf87114a9\n  [...]\n  * | | 2020-05-09 09:25:35 +0000 f258742372\n  * | | 2020-05-09 08:55:55 +0000 9c96a1cd72\n  * | | 2020-05-08 19:55:36 +0000 77f55bc175\n  [...]\n\nSo the actual \"bottom\" that we should send is 9c96a1cd72. But the\nhistory we get only goes down to c7883f4581. The tricky thing, though,\nis that that commit is a merge. The first parent is still something we\nwant to send, but the second parent is too old. And then the merge at\n9d282b0d7d has the same thing. The first parent is recent, but the\nsecond parent is old.\n\nI walked through upload-pack in a debugger, and its procedure looks\nsane. It does a revision walk with --max-age to come up with a list of\n\"not shallow\" commits, which include all three of those, as well as the\ncommits in between. And then for each not-shallow commit, it sees if any\nparents weren't visited, in which case we know we have a boundary. So\nthat commit gets marked as \"shallow\", to indicate that it will have its\nparents truncated. In this case, all three of the commits I mentioned\nget this. And indeed, if we use GIT_TRACE_PACKET, we can see that it\nmentions them (and only them):\n\n  packet:  upload-pack> shallow c7883f4581688909baf65c1219a8e842e369150b\n  packet:  upload-pack> shallow 9d282b0d7d2e05d7324e70afa66c4ff1306e67b7\n  packet:  upload-pack> shallow 9c96a1cd729d0209ba696f225b42d8aafd27295b\n\nBut here's the thing. We _don't_ want to mark those first two merges as\nfully shallow. We only want to ignore their second parents, but let them\ncontinue to traverse the first parents.\n\nI'm not sure if the shallow mechanism or protocol is even capable of\nrepresenting a partial graft like that. Maybe somebody who's more\nfamiliar with the shallow system can comment?\n\n-Peff\n"}]}