7

Git's fsck doc talks about "dangling" objects, while the gc doc talks only about "loose objects". There's a strict split.

But while skimming a few related SO posts, the terms seem to be used interchangeably. In the Git Book v2 and Git's source code as well:

   (main) $ git checkout v2.33.0
(225bc32) $ rg 'dangling (object|commit|blob|tag|tree)' | wc -l
      31
(225bc32) $ rg 'loose (object|commit|blob|tag|tree)' | wc -l
     117

Lastly, both commands are often used in sequence, and it seems clear to me from their behavior that they target the same things.

Thus, "dangling" and "loose" are just 2 similar terms for the same concept. Is this summary correct?


Or is "loose objects" rather a category, while "dangling" is reserved intentionally for the specific types of objects?

Katrin Leinweber
  • 1,316
  • 13
  • 33

1 Answers1

8
  • Loose objects - are those that aren't packed. Git can compress many loose objects into a single pack file.
  • Dangling object - is the one that's not referenced by anything (e.g. an orphan commit which has no branch/tag pointing to it). It's garbage that will at some point be collected by GC.
  • "Unreachable" object (see comment by @torek). If commit A is a parent of B, then A is not dangling even if B is. Instead A is "unreachable". It's also part of garbage.

Loose object can be dangling, packs can contain dangling objects. So these concepts are orthogonal. But you can create a reference (branch, tag) which will reference a dangling commit and it will stop "dangle".

Stanislav Bashkyrtsev
  • 14,470
  • 7
  • 42
  • 45
  • 2
    Thank you! That's what I was missing: "loose vs. _packed_", but "dangling vs. _referenced_" – Katrin Leinweber Sep 09 '21 at 07:28
  • 3
    @KatrinLeinweber, nicely said. Though "reachable" is probably a more accurate version of "referenced". – Stanislav Bashkyrtsev Sep 09 '21 at 07:32
  • 2
    For chainable objects (commits and trees) Git makes a distinction between "not referenced" / "not reachable", and "dangling". Suppose, e.g., you made commits I-J-K atop existing commit H at the end of branch B. Then you run `git reset B~3` to drop all three new commits: B now points to H, not K. All three are now unreferenced/unreachable, but only one is "dangling" as two *would* be reachable if the "dangling" end were made reachable. (This just shortens the output from git fsck, really.) – torek Sep 09 '21 at 16:46