Subject: Re: Poor performance of git describe in big repos

From: John Keeping <[email-masked]>
Date: Fri, 31 May 2013 09:32:52 +0100

On Fri, May 31, 2013 at 09:14:49AM +0100, Alex Bennée wrote:
> On 30 May 2013 20:30, John Keeping <[email-masked]> wrote:
> > On Thu, May 30, 2013 at 06:21:55PM +0200, Thomas Rast wrote:
> >> Alex Bennée <[email-masked]> writes:
> >>
> >> > On 30 May 2013 16:33, Thomas Rast <[email-masked]> wrote:
> >> >> Alex Bennée <[email-masked]> writes:
> > <snip>
> >> > Will it be loading the blob for every commit it traverses or just ones that hit
> >> > a tag? Why does it need to load the blob at all? Surely the commit
> >> > tree state doesn't
> >> > need to be walked down?
> >>
> >> No, my theory is that you tagged *the blobs*.  Git supports this.
> 
> Wait is this the difference between annotated and non-annotated tags?
> I thought a non-annotated just acted like references to a particular
> tree state?

No, this is something slightly different.  In Git there are four types
of object: tag, commit, tree and blob.  When you have a heavyweight tag,
the tag reference points at a tag object (which in turn points at
another object).  With a lightweight tag, the tag reference typically
points at a commit object.

However, there is no restriction that says that a tag object must point
to a commit or that a lightweight tag must point at a commit - it is
equally possible to point directly at a tree or a blob (although a lot
less common).

Thomas is suggesting that you might have a tag that does not point at a
commit but instead points to a blob object.

> > You can see if that is the case by doing something like this:
> >
> >     eval $(git for-each-ref --shell --format '
> >         test $(git cat-file -t %(objectname)^{}) = commit ||
> >         echo %(refname);')
> >
> > That will print out the name of any ref that doesn't point at a
> > commit.
> 
> Hmm that didn't seem to work.

You mean there was no output?  In that case it's likely that all your
references do indeed point at commits.

>                               But looking at the output by hand I
> certainly have a mix of tags that are commits vs tags:
> 
> 
> 09:08 ajb@sloy/x86_64 [work.git] >git for-each-ref | grep "refs/tags"
> | grep "commit" | wc -l
> 1345
> 09:12 ajb@sloy/x86_64 [work.git] >git for-each-ref | grep "refs/tags"
> | grep -v "commit" | wc -l
> 66

This means that you have 1345 lightweight tags and 66 heavyweight tags,
assuming that all of the lines that don't say "commit" do say "tag".

By the way, I don't remember if you said which version of Git you're
using.  If it's an older version then it's possible that something has
changed.