1

I'm doing some work with git gc and I noticed some behavior I don't understand and cannot reconcile in the docs. This pertains to checking for dangling commits with the git fsck utility.

Consider the following simple steps:

  1. Create a new feature branch, and make one commit.
  2. Switch back to master, and delete feature without merging.
  3. Check the reflog, as expected your commit is there.

Now, when I run git fsck, I (correctly?) don't see a dangling commit. According to this highly voted answer:

Note that commits referred to from your reflog are considered reachable.

And

And because a commit is only called dangling when it has nothing pointing to it – including reflog entries –, “reflogs for dangling commits” are not a thing.

Based on this explanation, it would be expected that Git doesn't consider the commits in my example as dangling, because they are still reachable via the reflog.

If I expire unreachable objects from the reflog, then a simple git fsck will now show this commit as dangling.

However, assume I didn't expire the reflog. If I run git fsck --lost-found, Git now lists this commit as dangling, even though it still exists in the reflog.

From what I could find in the docs, nothing is said about --lost-found redefining what constitutes a dangling commit, or any other implied exception.

My question is, are (un?)reachable commits in the reflog dangling or not? If not, why does the --lost-found flag make them so?

silencedogood
  • 3,209
  • 1
  • 11
  • 36
  • It's probably a bug in `git fsck`. If it's not a bug in `git fsck`, it's a bug in the `git fsck` documentation. Either reflogs make commits reachable and they are therefore not dangling and hence not lost, or `--lost-found` implies `--no-reflogs` and that should be mentioned in the documentation. – torek Oct 20 '22 at 08:48
  • @torek The thing is, if the reflog makes all entries reachable, then why does Git have the `git reflog expire --expire-unreachable` option? I think that perhaps the definition in the docs (and elsewhere) is incorrect, and that Git **does** in fact consider orphaned objects in the reflog to be unreachable. Hard to say really, because so much documentation supports the notion that reflog entries are reachable. – silencedogood Oct 20 '22 at 13:48
  • `git reflog expire` is quite different: it looks at the *date stamp* in each reflog entry, and also categorizes each reflog entry's hash ID as "reachable from current ref value" or "not reachable from current ref value". Suppose the current ref value is `a123456` and the stored hash ID in entry #12 is `b789abc`. If `b789abc` is an ancestor of `a123456`, this entry, #12, survives if its timestamp is 70 days old, but if it is *not* an ancestor, #12 gets pruned because 70 > 30 (this assumes the defaults of 90 and 30 days for the expiry values). – torek Oct 21 '22 at 07:46
  • So, reachable vs unreachable for `git reflog expire` is an entirely different question: it means "object located by this entry is an ancestor of corresponding ref". Compare with `git fsck` for which "reachable" means *reachable from any live ref or reflog entry or index entry etc* (except as modified by flags). – torek Oct 21 '22 at 07:48
  • This is ... not documented well. :-) – torek Oct 21 '22 at 07:48
  • @torek Ahh okay thanks for clarification on that. So it's likely an issue with the `fsck` utility's `--lost-found` flag then. I mainly just wanted to make sure I wasn't somehow misinterpreting the meaning of unreachable (and hence dangling). Still would be nice to know exactly what's up with fsck returning stuff in the reflog. – silencedogood Oct 23 '22 at 22:05

0 Answers0