[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [jgit-dev] Commits and tags

On Thu, Jun 14, 2012 at 3:10 AM, Alex Buloichik <alex73mail@xxxxxxxxx> wrote:
>
> I need to find last tagged commit in my branch.
> http://stackoverflow.com/questions/7501646/jgit-retrieve-tag-associated-with-a-git-commit?rq=1

What you really want is describe, which is apparently hung up in code
review still.

  https://git.eclipse.org/r/4060

> doesn't help me because git.tagList().call() returns List<Ref> instead
> List<RevTag>.
>
> As far as I understand, I can get reference to tagged RevCommit by
> tagRef.getPeeledObjectId(). Am I right ?

Sort of. You actually need to ensure the tagRef is peeled, which is
usually done by:

  tagRef = repository.peel(tagRef);

If the tag is a lightweight tag, you have to compare
tagRef.getObjectId() because its tagRef.getPeeledObjectId() is still
null. This is because a lightweight tag is just a name pointing to a
commit. If the tag is an annotated tag, after peel the
getPeeledObjectId() will be non-null and would reference the tagged
commit.

> So, I created RevWalk by code:
>
> Ref ref = gitRepository.getRef(Constants.HEAD);
> RevWalk walk = new RevWalk(gitRepository);
> walk.markStart(walk.parseCommit(ref.getObjectId()));
> for (RevCommit commit : walk) {
>  ...
> }
>
> I have correct list of commits from latest to earlier, and I want to
> compare each commit with tags. I retrieved tags by
> gitRepository.getTags(). Refs in this map pointed to tag, not to
> commit. Just like in .git/refs/tags/* files. But for all tags in this
> map, tagRef.getPeeledObjectID() is always null.

This is a performance optimization performed by both JGit and CGit.
Tags in the .git/refs/tags/* directory tree just contain the tag's
SHA-1. They do not know the commit SHA-1 "easily". So reading these
references only tells you the tag SHA-1 and the application must
decide if it will expend more time to peel these, or if just knowing
the tag SHA-1 is sufficient for its needs. At this level of the JGit
API you need to do the peel yourself if your application must have the
data.

> After that, I runned "git gc" from command line, then it moved tags to
> .git/packed-refs file. After that, tagRef.getPeeledObjectId() contains
> correct ID for commit.
>
> So, am I using correct algorithm for find last tagged commit ? Why
> tagRef.getPeeledObjectId() works only after "git gc" ? Is it jgit bug
> ?

This is an intentional performance optimization/feature; not a bug.

Both JGit and CGit create a tag by storing only the tag SHA-1 into the
.git/refs/tags/NAME file. This isn't too bad to peel on demand with
the repository.peel(Ref) method when there is only one. But after a
few hundred tags, peeling on demand gets really slow. So the
packed-refs file came about as a way to combine these small references
together to save disk space, to reduce the time it takes to load...
and someone had the bright idea of caching the peeled data in the
file.