{"thread":{"id":"50607","subject":"[PATCH] doc/fsck: discuss mix of --connectivity-only and --dangling","startedAt":"2019-02-27T14:55:53Z","lastAt":"2019-03-05T04:47:43Z","messageCount":7,"participants":["Jeff King","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"370310","messageId":"20190227145549.GA3255@sigill.intra.peff.net","threadId":"50607","inReplyTo":null,"subject":"[PATCH] doc/fsck: discuss mix of --connectivity-only and --dangling","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2019-02-27T14:55:49Z","receivedAt":"2019-02-27T14:55:53Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"The --connectivity-only option avoids opening every object, and instead\njust marks reachable objects with a flag, and compares this to the set\nof all objects. This strategy is discussed in more detail in 3e3f8bd608\n(fsck: prepare dummy objects for --connectivity-check, 2017-01-17).\n\nThis means that we report _every_ unreachable object as dangling.\nWhereas in a full fsck, we'd have actually opened and parsed each of\nthose unreachable objects, marking their child objects with the USED\nflag, to mean \"this was mentioned by another object\". And thus we can\nreport only the tip of an unreachable segment of the object graph as\ndangling.\n\nYou can see this difference with a trivial example:\n\n  tree=$(git hash-object -t tree -w /dev/null)\n  one=$(echo one | git commit-tree $tree)\n  two=$(echo two | git commit-tree -p $one $tree)\n\nRunning `git fsck` will report only $two as dangling, but with\n--connectivity-only, both commits (and the tree) are reported.\n\nWe could make the two cases work identically by taking a separate pass\nover the unreachable objects, parsing them and marking objects they\nrefer to as USED. That would still avoid parsing any blobs, but we'd pay\nthe cost to access any unreachable commits and trees. Since the point of\n--connectivity-only is to quickly report whether all reachable objects\nare present, I'd argue that it's not worth slowing it down to produce\na better-analyzed dangling list.\n\nInstead, let's document this somewhat surprising property of\nconnectivity-only. If somebody really wants to the extra analysis, we\ncan add a separate option to enable it.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\n Documentation/git-fsck.txt | 4 ++++\n 1 file changed, 4 insertions(+)\n\ndiff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.txt\nindex 55950d9eea..02ce7c6282 100644\n--- a/Documentation/git-fsck.txt\n+++ b/Documentation/git-fsck.txt\n@@ -65,6 +65,10 @@ index file, all SHA-1 references in `refs` namespace, and all reflogs\n \tCheck only the connectivity of tags, commits and tree objects. By\n \tavoiding to unpack blobs, this speeds up the operation, at the\n \texpense of missing corrupt objects or other problematic issues.\n+\tNote that this also skips some analysis of unreachable objects,\n+\tmeaning that Git will report the full list of unreachable\n+\tobjects as dangling (unless `--no-dangling` was used), rather\n+\tthan the tips of unreachable segments of history.\n \n --strict::\n \tEnable more strict checking, namely to catch a file mode\n-- \n2.21.0.675.g01c085a870\n"},{"id":"370311","messageId":"20190227145928.GA3727@sigill.intra.peff.net","threadId":"50607","inReplyTo":"20190227145549.GA3255@sigill.intra.peff.net","subject":"Re: [PATCH] doc/fsck: discuss mix of --connectivity-only and --dangling","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2019-02-27T14:59:28Z","receivedAt":"2019-02-27T14:59:32Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Feb 27, 2019 at 09:55:49AM -0500, Jeff King wrote:\n\n> We could make the two cases work identically by taking a separate pass\n> over the unreachable objects, parsing them and marking objects they\n> refer to as USED. That would still avoid parsing any blobs, but we'd pay\n> the cost to access any unreachable commits and trees. Since the point of\n> --connectivity-only is to quickly report whether all reachable objects\n> are present, I'd argue that it's not worth slowing it down to produce\n> a better-analyzed dangling list.\n> \n> Instead, let's document this somewhat surprising property of\n> connectivity-only. If somebody really wants to the extra analysis, we\n> can add a separate option to enable it.\n\nI'm actually a little torn on this. We could consider this a bug, and\nthe \"option\" to disable it when you want things to go fast is to say\n\"--no-dangling\". That leaves no way to say \"show me the list of\nunreachable objects, but don't bother spending extra time on dangling\nanalysis\". But I don't think I've ever really wanted that list of\nunreachable objects anyway (and besides, you could do it pretty easily\nwith cat-file, rev-list, and comm).\n\nSo I sketched up what it might look like to just fix the bug (but kick\nin only when needed), which is below.\n\ndiff --git a/builtin/fsck.c b/builtin/fsck.c\nindex bb4227bebc..d26fb0a044 100644\n--- a/builtin/fsck.c\n+++ b/builtin/fsck.c\n@@ -235,6 +235,48 @@ static int mark_used(struct object *obj, int type, void *data, struct fsck_optio\n \treturn 0;\n }\n \n+static void mark_unreachable_referents(const struct object_id *oid)\n+{\n+\tstruct fsck_options options = FSCK_OPTIONS_DEFAULT;\n+\tstruct object *obj = lookup_object(the_repository, oid->hash);\n+\n+\tif (!obj || !(obj->flags & HAS_OBJ))\n+\t\treturn; /* not part of our original set */\n+\tif (obj->flags & REACHABLE)\n+\t\treturn; /* reachable objects already traversed */\n+\n+\t/*\n+\t * Avoid passing OBJ_NONE to fsck_walk, which will parse the object\n+\t * (and we want to avoid parsing blobs).\n+\t */\n+\tif (obj->type == OBJ_NONE) {\n+\t\tenum object_type type = oid_object_info(the_repository,\n+\t\t\t\t\t\t\t&obj->oid, NULL);\n+\t\tif (type > 0)\n+\t\t\tobject_as_type(the_repository, obj, type, 0);\n+\t}\n+\n+\toptions.walk = mark_used;\n+\tfsck_walk(obj, NULL, &options);\n+}\n+\n+static int mark_loose_unreachable_referents(const struct object_id *oid,\n+\t\t\t\t\t    const char *path,\n+\t\t\t\t\t    void *data)\n+{\n+\tmark_unreachable_referents(oid);\n+\treturn 0;\n+}\n+\n+static int mark_packed_unreachable_referents(const struct object_id *oid,\n+\t\t\t\t\t     struct packed_git *pack,\n+\t\t\t\t\t     uint32_t pos,\n+\t\t\t\t\t     void *data)\n+{\n+\tmark_unreachable_referents(oid);\n+\treturn 0;\n+}\n+\n /*\n  * Check a single reachable object\n  */\n@@ -347,6 +389,26 @@ static void check_connectivity(void)\n \t/* Traverse the pending reachable objects */\n \ttraverse_reachable();\n \n+\t/*\n+\t * With --connectivity-only, we won't have actually opened and marked\n+\t * unreachable objects with USED. Do that now to make --dangling, etc\n+\t * accurate.\n+\t */\n+\tif (connectivity_only && (show_dangling || write_lost_and_found)) {\n+\t\t/*\n+\t\t * Even though we already have a \"struct object\" for each of\n+\t\t * these in memory, we must not iterate over the internal\n+\t\t * object hash as we do below. Our loop would potentially\n+\t\t * resize the hash, making our iteration invalid.\n+\t\t *\n+\t\t * Instead, we'll just go back to the source list of objects,\n+\t\t * and ignore any that weren't present in our earlier\n+\t\t * traversal.\n+\t\t */\n+\t\tfor_each_loose_object(mark_loose_unreachable_referents, NULL, 0);\n+\t\tfor_each_packed_object(mark_packed_unreachable_referents, NULL, 0);\n+\t}\n+\n \t/* Look up all the requirements, warn about missing objects.. */\n \tmax = get_max_object_index();\n \tif (verbose)\ndiff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh\nindex c61f972141..49f08d5b9c 100755\n--- a/t/t1450-fsck.sh\n+++ b/t/t1450-fsck.sh\n@@ -740,7 +740,7 @@ test_expect_success 'fsck detects truncated loose object' '\n # for each of type, we have one version which is referenced by another object\n # (and so while unreachable, not dangling), and another variant which really is\n # dangling.\n-test_expect_success 'fsck notices dangling objects' '\n+test_expect_success 'create dangling-object repository' '\n \tgit init dangling &&\n \t(\n \t\tcd dangling &&\n@@ -751,19 +751,34 @@ test_expect_success 'fsck notices dangling objects' '\n \t\tcommit=$(git commit-tree $tree) &&\n \t\tdcommit=$(git commit-tree -p $commit $tree) &&\n \n-\t\tcat >expect <<-EOF &&\n+\t\tcat >expect <<-EOF\n \t\tdangling blob $dblob\n \t\tdangling commit $dcommit\n \t\tdangling tree $dtree\n \t\tEOF\n+\t)\n+'\n \n+test_expect_success 'fsck notices dangling objects' '\n+\t(\n+\t\tcd dangling &&\n \t\tgit fsck >actual &&\n \t\t# the output order is non-deterministic, as it comes from a hash\n \t\tsort <actual >actual.sorted &&\n \t\ttest_i18ncmp expect actual.sorted\n \t)\n '\n \n+test_expect_success 'fsck --connectivity-only notices dangling objects' '\n+\t(\n+\t\tcd dangling &&\n+\t\tgit fsck --connectivity-only >actual &&\n+\t\t# the output order is non-deterministic, as it comes from a hash\n+\t\tsort <actual >actual.sorted &&\n+\t\ttest_i18ncmp expect actual.sorted\n+\t)\n+'\n+\n test_expect_success 'fsck $name notices bogus $name' '\n \ttest_must_fail git fsck bogus &&\n \ttest_must_fail git fsck $ZERO_OID\n"},{"id":"370400","messageId":"xmqqlg1z9uko.fsf@gitster-ct.c.googlers.com","threadId":"50607","inReplyTo":"20190227145928.GA3727@sigill.intra.peff.net","subject":"Re: [PATCH] doc/fsck: discuss mix of --connectivity-only and --dangling","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-03-01T02:50:31Z","receivedAt":"2019-03-01T02:50:38Z","isPatch":true,"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 actually a little torn on this. We could consider this a bug, and\n> the \"option\" to disable it when you want things to go fast is to say\n> \"--no-dangling\". That leaves no way to say \"show me the list of\n> unreachable objects, but don't bother spending extra time on dangling\n> analysis\". But I don't think I've ever really wanted that list of\n> unreachable objects anyway (and besides, you could do it pretty easily\n> with cat-file, rev-list, and comm).\n>\n> So I sketched up what it might look like to just fix the bug (but kick\n> in only when needed), which is below.\n\n[jch: I am still mostly offline til the next week, but I had a\nchance to sit in front of my mailbox long enough, so...]\n\nAs the primariy purose of the --conn-only option being such, perhaps\nwe should have made --no-dangling the default when --conn-only is in\neffect.\n\nBut if --conn-only is made to do the right thing while showing\ndangling and unreachable properly sifted into their own bins, like\nthis patch does, what's the difference between that and the normal\n--no-conn-only, other than performance and corrupt blobs left\nunreported?  Perhaps if we are going that route, it might even make\nsense to rename --conn-only to --skip-parsing-blobs or something.\n\nThanks.\n\n"},{"id":"370660","messageId":"20190305042601.GF19800@sigill.intra.peff.net","threadId":"50607","inReplyTo":"xmqqlg1z9uko.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH] doc/fsck: discuss mix of --connectivity-only and --dangling","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2019-03-05T04:26:01Z","receivedAt":"2019-03-05T04:26:04Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Mar 01, 2019 at 11:50:31AM +0900, Junio C Hamano wrote:\n\n> > I'm actually a little torn on this. We could consider this a bug, and\n> > the \"option\" to disable it when you want things to go fast is to say\n> > \"--no-dangling\". That leaves no way to say \"show me the list of\n> > unreachable objects, but don't bother spending extra time on dangling\n> > analysis\". But I don't think I've ever really wanted that list of\n> > unreachable objects anyway (and besides, you could do it pretty easily\n> > with cat-file, rev-list, and comm).\n> >\n> > So I sketched up what it might look like to just fix the bug (but kick\n> > in only when needed), which is below.\n> \n> As the primariy purose of the --conn-only option being such, perhaps\n> we should have made --no-dangling the default when --conn-only is in\n> effect.\n\nYes, perhaps. Though after thinking on this for a few days, I actually\nthink there is no real reason not to just have --dangling do the right\nthing here (and we're still much faster than a full fsck, and not much\nslower than the current code unless you happen to have a large number\nof unreachable commits and trees).\n\nAnd then if the user says \"--no-dangling\", we can be even faster (i.e.,\nthe same as the current code).\n\nWe could also make \"--no-dangling\" the default for\n\"--connectivity-only\", though I do not have a strong feeling either way.\n\n> But if --conn-only is made to do the right thing while showing\n> dangling and unreachable properly sifted into their own bins, like\n> this patch does, what's the difference between that and the normal\n> --no-conn-only, other than performance and corrupt blobs left\n> unreported?  Perhaps if we are going that route, it might even make\n> sense to rename --conn-only to --skip-parsing-blobs or something.\n\nIn addition to not opening blobs, we won't actually do fsck checks on\nany of the objects. So in git.git, for instance, we do not warn about\nthe missing tagger in the v0.99 tag when --connectivity-only is in use.\n\n-Peff\n"},{"id":"370661","messageId":"20190305044530.GG19800@sigill.intra.peff.net","threadId":"50607","inReplyTo":"20190305042601.GF19800@sigill.intra.peff.net","subject":"[PATCH v2 0/2] fsck --connectivity-only --dangling","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2019-03-05T04:45:30Z","receivedAt":"2019-03-05T04:45:34Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Mar 04, 2019 at 11:26:01PM -0500, Jeff King wrote:\n\n> > > So I sketched up what it might look like to just fix the bug (but kick\n> > > in only when needed), which is below.\n> > \n> > As the primariy purose of the --conn-only option being such, perhaps\n> > we should have made --no-dangling the default when --conn-only is in\n> > effect.\n> \n> Yes, perhaps. Though after thinking on this for a few days, I actually\n> think there is no real reason not to just have --dangling do the right\n> thing here (and we're still much faster than a full fsck, and not much\n> slower than the current code unless you happen to have a large number\n> of unreachable commits and trees).\n> \n> And then if the user says \"--no-dangling\", we can be even faster (i.e.,\n> the same as the current code).\n> \n> We could also make \"--no-dangling\" the default for\n> \"--connectivity-only\", though I do not have a strong feeling either way.\n\nSo here's a re-rolled series. The first patch just clarifies how\n--connectivity-only works, since there are a few subtle points that came\nup in this thread.\n\nThe second one is my fix from before. That lets us drop the initial\n\"explain why it doesn't work\" documentation patch, though I did add a\nnote to the documentation pointing the user to --no-dangling.\n\n  [1/2]: doc/fsck: clarify --connectivity-only behavior\n  [2/2]: fsck: always compute USED flags for unreachable objects\n\n Documentation/git-fsck.txt | 14 +++++++--\n builtin/fsck.c             | 62 ++++++++++++++++++++++++++++++++++++++\n t/t1450-fsck.sh            | 19 ++++++++++--\n 3 files changed, 90 insertions(+), 5 deletions(-)\n\n-Peff\n"},{"id":"370662","messageId":"20190305044637.GA32325@sigill.intra.peff.net","threadId":"50607","inReplyTo":"20190305044530.GG19800@sigill.intra.peff.net","subject":"[PATCH v2 1/2] doc/fsck: clarify --connectivity-only behavior","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2019-03-05T04:46:38Z","receivedAt":"2019-03-05T04:46:41Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On reading this again, there are two things that were not immediately\nclear to me:\n\n  - we do still check links to blobs, even though we don't open the\n    blobs themselves\n\n  - we do not do the normal fsck checks, even for non-blob objects we do\n    open\n\nLet's reword it to make these points a little more clear.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\n Documentation/git-fsck.txt | 10 +++++++---\n 1 file changed, 7 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.txt\nindex 55950d9eea..b7c7ac0866 100644\n--- a/Documentation/git-fsck.txt\n+++ b/Documentation/git-fsck.txt\n@@ -62,9 +62,13 @@ index file, all SHA-1 references in `refs` namespace, and all reflogs\n \twith --no-full.\n \n --connectivity-only::\n-\tCheck only the connectivity of tags, commits and tree objects. By\n-\tavoiding to unpack blobs, this speeds up the operation, at the\n-\texpense of missing corrupt objects or other problematic issues.\n+\tCheck only the connectivity of reachable objects, making sure\n+\tthat any objects referenced by a reachable tag, commit, or tree\n+\tis present. This speeds up the operation by avoiding reading\n+\tblobs entirely (though it does still check that referenced blobs\n+\texist). This will detect corruption in commits and trees, but\n+\tnot do any semantic checks (e.g., for format errors). Corruption\n+\tin blob objects will not be detected at all.\n \n --strict::\n \tEnable more strict checking, namely to catch a file mode\n-- \n2.21.0.684.gc9dc8b89c9\n\n"},{"id":"370663","messageId":"20190305044739.GB32325@sigill.intra.peff.net","threadId":"50607","inReplyTo":"20190305044530.GG19800@sigill.intra.peff.net","subject":"[PATCH v2 2/2] fsck: always compute USED flags for unreachable objects","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2019-03-05T04:47:39Z","receivedAt":"2019-03-05T04:47:43Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"The --connectivity-only option avoids opening every object, and instead\njust marks reachable objects with a flag and compares this to the set\nof all objects. This strategy is discussed in more detail in 3e3f8bd608\n(fsck: prepare dummy objects for --connectivity-check, 2017-01-17).\n\nThis means that we report _every_ unreachable object as dangling.\nWhereas in a full fsck, we'd have actually opened and parsed each of\nthose unreachable objects, marking their child objects with the USED\nflag, to mean \"this was mentioned by another object\". And thus we can\nreport only the tip of an unreachable segment of the object graph as\ndangling.\n\nYou can see this difference with a trivial example:\n\n  tree=$(git hash-object -t tree -w /dev/null)\n  one=$(echo one | git commit-tree $tree)\n  two=$(echo two | git commit-tree -p $one $tree)\n\nRunning `git fsck` will report only $two as dangling, but with\n--connectivity-only, both commits (and the tree) are reported. Likewise,\nusing --lost-found would write all three objects.\n\nWe can make --connectivity-only work like the normal case by taking a\nseparate pass over the unreachable objects, parsing them and marking\nobjects they refer to as USED. That still avoids parsing any blobs,\nthough we do pay the cost to access any unreachable commits and trees\n(which may or may not be noticeable, depending on how many you have).\n\nIf neither --dangling nor --lost-found is in effect, then we can skip\nthis step entirely, just like we do now. That makes \"--connectivity-only\n--no-dangling\" just as fast as the current \"--connectivity-only\". I.e.,\nwe do the correct thing always, but you can still tweak the options to\nmake it faster if you don't care about dangling objects.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\n Documentation/git-fsck.txt |  4 +++\n builtin/fsck.c             | 62 ++++++++++++++++++++++++++++++++++++++\n t/t1450-fsck.sh            | 19 ++++++++++--\n 3 files changed, 83 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.txt\nindex b7c7ac0866..e0eae642c1 100644\n--- a/Documentation/git-fsck.txt\n+++ b/Documentation/git-fsck.txt\n@@ -69,6 +69,10 @@ index file, all SHA-1 references in `refs` namespace, and all reflogs\n \texist). This will detect corruption in commits and trees, but\n \tnot do any semantic checks (e.g., for format errors). Corruption\n \tin blob objects will not be detected at all.\n++\n+Unreachable tags, commits, and trees will also be accessed to find the\n+tips of dangling segments of history. Use `--no-dangling` if you don't\n+care about this output and want to speed it up further.\n \n --strict::\n \tEnable more strict checking, namely to catch a file mode\ndiff --git a/builtin/fsck.c b/builtin/fsck.c\nindex bb4227bebc..d26fb0a044 100644\n--- a/builtin/fsck.c\n+++ b/builtin/fsck.c\n@@ -235,6 +235,48 @@ static int mark_used(struct object *obj, int type, void *data, struct fsck_optio\n \treturn 0;\n }\n \n+static void mark_unreachable_referents(const struct object_id *oid)\n+{\n+\tstruct fsck_options options = FSCK_OPTIONS_DEFAULT;\n+\tstruct object *obj = lookup_object(the_repository, oid->hash);\n+\n+\tif (!obj || !(obj->flags & HAS_OBJ))\n+\t\treturn; /* not part of our original set */\n+\tif (obj->flags & REACHABLE)\n+\t\treturn; /* reachable objects already traversed */\n+\n+\t/*\n+\t * Avoid passing OBJ_NONE to fsck_walk, which will parse the object\n+\t * (and we want to avoid parsing blobs).\n+\t */\n+\tif (obj->type == OBJ_NONE) {\n+\t\tenum object_type type = oid_object_info(the_repository,\n+\t\t\t\t\t\t\t&obj->oid, NULL);\n+\t\tif (type > 0)\n+\t\t\tobject_as_type(the_repository, obj, type, 0);\n+\t}\n+\n+\toptions.walk = mark_used;\n+\tfsck_walk(obj, NULL, &options);\n+}\n+\n+static int mark_loose_unreachable_referents(const struct object_id *oid,\n+\t\t\t\t\t    const char *path,\n+\t\t\t\t\t    void *data)\n+{\n+\tmark_unreachable_referents(oid);\n+\treturn 0;\n+}\n+\n+static int mark_packed_unreachable_referents(const struct object_id *oid,\n+\t\t\t\t\t     struct packed_git *pack,\n+\t\t\t\t\t     uint32_t pos,\n+\t\t\t\t\t     void *data)\n+{\n+\tmark_unreachable_referents(oid);\n+\treturn 0;\n+}\n+\n /*\n  * Check a single reachable object\n  */\n@@ -347,6 +389,26 @@ static void check_connectivity(void)\n \t/* Traverse the pending reachable objects */\n \ttraverse_reachable();\n \n+\t/*\n+\t * With --connectivity-only, we won't have actually opened and marked\n+\t * unreachable objects with USED. Do that now to make --dangling, etc\n+\t * accurate.\n+\t */\n+\tif (connectivity_only && (show_dangling || write_lost_and_found)) {\n+\t\t/*\n+\t\t * Even though we already have a \"struct object\" for each of\n+\t\t * these in memory, we must not iterate over the internal\n+\t\t * object hash as we do below. Our loop would potentially\n+\t\t * resize the hash, making our iteration invalid.\n+\t\t *\n+\t\t * Instead, we'll just go back to the source list of objects,\n+\t\t * and ignore any that weren't present in our earlier\n+\t\t * traversal.\n+\t\t */\n+\t\tfor_each_loose_object(mark_loose_unreachable_referents, NULL, 0);\n+\t\tfor_each_packed_object(mark_packed_unreachable_referents, NULL, 0);\n+\t}\n+\n \t/* Look up all the requirements, warn about missing objects.. */\n \tmax = get_max_object_index();\n \tif (verbose)\ndiff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh\nindex c61f972141..49f08d5b9c 100755\n--- a/t/t1450-fsck.sh\n+++ b/t/t1450-fsck.sh\n@@ -740,7 +740,7 @@ test_expect_success 'fsck detects truncated loose object' '\n # for each of type, we have one version which is referenced by another object\n # (and so while unreachable, not dangling), and another variant which really is\n # dangling.\n-test_expect_success 'fsck notices dangling objects' '\n+test_expect_success 'create dangling-object repository' '\n \tgit init dangling &&\n \t(\n \t\tcd dangling &&\n@@ -751,19 +751,34 @@ test_expect_success 'fsck notices dangling objects' '\n \t\tcommit=$(git commit-tree $tree) &&\n \t\tdcommit=$(git commit-tree -p $commit $tree) &&\n \n-\t\tcat >expect <<-EOF &&\n+\t\tcat >expect <<-EOF\n \t\tdangling blob $dblob\n \t\tdangling commit $dcommit\n \t\tdangling tree $dtree\n \t\tEOF\n+\t)\n+'\n \n+test_expect_success 'fsck notices dangling objects' '\n+\t(\n+\t\tcd dangling &&\n \t\tgit fsck >actual &&\n \t\t# the output order is non-deterministic, as it comes from a hash\n \t\tsort <actual >actual.sorted &&\n \t\ttest_i18ncmp expect actual.sorted\n \t)\n '\n \n+test_expect_success 'fsck --connectivity-only notices dangling objects' '\n+\t(\n+\t\tcd dangling &&\n+\t\tgit fsck --connectivity-only >actual &&\n+\t\t# the output order is non-deterministic, as it comes from a hash\n+\t\tsort <actual >actual.sorted &&\n+\t\ttest_i18ncmp expect actual.sorted\n+\t)\n+'\n+\n test_expect_success 'fsck $name notices bogus $name' '\n \ttest_must_fail git fsck bogus &&\n \ttest_must_fail git fsck $ZERO_OID\n-- \n2.21.0.684.gc9dc8b89c9\n"}]}