Subject: Re: fsck --full is Ok, but clones are not, "missing commits"?!

From: Johannes Sixt <[email-masked]>
Date: Thu, 17 Apr 2008 08:18:39 +0200

Dmitry Potapov schrieb:
> On Wed, Apr 16, 2008 at 04:56:08PM +0200, Johannes Sixt wrote:
>> Actually, no. The trouble is that *all* tools obey grafts. Hence,
>> git-repack -f -d -a will remove the hidden objects. But a subsequent fsck
>> won't notice, because it *also* obeys the grafts. git prune will remove
>> hidden objects only as long as they are loose; if they are already packed,
>> then only a repack -f will remove them.
> 
> I use git 1.5.5 and I have a script that creates are repo with a hidden
> commit and then it cleans the reflog cleaned (as it would be happen after
> expiration of gc.reflogExpire). Then I run 'git-repack -f -d -a' and the
> hidden commit still presents, but when I run 'git prune' then the hidden
> object disappear. You can try it for yourself. Here is the script, I used:

And the reason for this is...

> 
> ===
> #!/bin/sh
> 
> set -e
> 
> mkdir t5
> cd t5
> git init
> 
> echo 1 > foo
> git add foo
> git commit -m 'add foo'
> R1=$(git rev-parse HEAD)
> 
> echo 2 >> foo
> git commit -m 'edit foo' -a
> R2=$(git rev-parse HEAD)
> 
> echo 3 >> foo
> git commit -m 'edit foo again' -a
> R3=$(git rev-parse HEAD)
> 
> set -x
> git log
> echo "$R3 $R1" > .git/info/grafts
> git log
> git-fsck --unreachable
> : > .git/logs/HEAD
> : > .git/logs/refs/heads/master
> git-fsck --unreachable
> git gc

... at this point the hidden commit still exists as loose objects (because
the repack inside gc didn't see the commit), and therefore...

> git-fsck --unreachable
> git-repack -f -d -a

... this does not make a difference at all.

> git-fsck --unreachable
> git prune

Here you remove the loose objects (because prune doesn't see the commit,
either), and by doing so you corrupt the repository.

> git-fsck --unreachable
> ===

A repack -a -d makes a difference if info/grafts is installed *after* the
first repack/gc.

-- Hannes