Florian Kaufmann
Florian Kaufmann

Reputation: 803

git fsck misses to report a tree object as unreachable

I'd like that git prints me all unreachable objects, not considering commits that are only reachable by reflog entries as reachable. git fsck --unreachable --no-reflogs misses to print a tree object which I know is unreachable. I am using git version 2.5.0. Am I missing something?

The following is a proof that there are unreachable tree objects which fsck does not print.

$ git init
Initialized empty Git repository in /somepath/.git/
$ echo hello >myfile
$ git add myfile
$ git commit -m initial
[master (root-commit) 30a7654] initial
 1 file changed, 1 insertion(+)
 create mode 100644 myfile
$ echo world >>myfile

The following commit creates three objects: a commit, a tree and a blob:

$ git commit -am 2nd
[master 4b96227] 2nd
 1 file changed, 1 insertion(+)

We make these three objects unreachable. fsck only reports the commit and the blob object as unreachable, but not the tree object:

$ git reset --hard HEAD^
HEAD is now at 30a7654 initial
$ git fsck --unreachable --no-reflogs
Checking object directories: 100% (256/256), done.
unreachable commit 4b96227ebf01b6947dd5710b6494f5e92cd62d49
unreachable blob 94954abda49de8615a048f8d2e64b5de848e27a1

prune does report all three object as unreachable, including the tree object:

$ git reflog expire --expire=all --all
$ git prune --expire now -vn
1df502bff6e2a54e686a0a5eb4033fb6cd160ba1 tree
4b96227ebf01b6947dd5710b6494f5e92cd62d49 commit
94954abda49de8615a048f8d2e64b5de848e27a1 blob

Upvotes: 2

Views: 779

Answers (1)

torek
torek

Reputation: 488183

You are correct that git fsck fails to report unreachable trees. You can create additional unreachable trees using git write-tree with an index that you do not commit (e.g., git add something, then git rm --cached the same entry after writing the tree; or use git update-index to manipulate the index more directly before and after using git write-tree).

I think the Git folks consider this a feature rather than a bug, on the theory that no one cares about trees.

Note that the documentation describes the --lost-found flag as restoring dangling commits and blobs. It also (experimentally) restores annotated tag objects that are delinked from their external refs/tags/ reference, but when it does so it just writes the object name into the file name in .git/lost-found/other/:

$ cat .git/lost-found/other/9c6db16bcff193bd5a814ce5bcda40027713ed8a
9c6db16bcff193bd5a814ce5bcda40027713ed8a
$ git cat-file -t 9c6db16bcff193bd5a814ce5bcda40027713ed8a
tag

It would make more sense to expand the contents of the tag object, the way Git does for blob objects. Git could even do this for trees, but just as --unreachable ignores them, so does --lost-found.

Upvotes: 2

Related Questions