Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does peel mean in Git?

Tags:

git

In trying to understand JGit: Retrieve tag associated with a git commit, I arrived at this thread on the JGit mailing list: [jgit-dev] Commits and tags.

In this thread they refer to the peel method of org.eclipse.jgit.lib.Repository:

Peel a possibly unpeeled reference to an annotated tag.

I could only find two mentions of peeling in the Git documentation: git-check-ref-format(1) Manual Page and Git Internals - Maintenance and Data Recovery.

What does the term peel mean in Git? How is it useful? What does it have to do with onions?

like image 947
Ed I Avatar asked Oct 21 '14 17:10

Ed I


2 Answers

You already know that each object in a repository has a unique SHA-1, and also an associated type and contents. (From the command line, use git cat-file -t sha1 to see the type of the given object, and git cat-file -p sha1 to see the contents, possibly with some pretty-printing applied but generally fairly raw in format.)

An annotated tag object in a git repository contains an SHA-1. (I hope this part is clear and uncontroversial. :-) )

Typically, the SHA-1 inside an annotated tag object—let's call this the "target-ID", and the object thus named the "target" of the tag—is the ID of a commit object. In this case, all is still pretty clear and simple. But what if it's not?

In particular, the target of an annotated tag might be another annotated tag. If this is the case, you must fetch that second annotated tag, which contains yet another target-ID. You must repeat this process, peeling off tag after tag, until you arrive at a non-tag object. Ideally this will be a commit, but of course it could be any of the remaining three kinds of objects (it's not clear what it means to tag a tree or blob though; only a commit makes sense).

This "peeling" process has been compared to peeling an onion, and that's where the phrase originates.

Note that if you're writing a repository health checker, it might be wise to make sure that the chain of tags does not loop (e.g., what if tag 1234567 has 7654321 as its target, and 7654321 is an annotated tag with 1234567 as its target?). (Edit: as remram points out in a comment, this requires "breaking" SHA-1. That means it's almost impossible for it to happen in practice, just as you won't get a tree that recursively points to itself.)

Edit: how to make a tag that points to another tag:

... make a repo with a commit that can be tagged ...
$ git tag -a anno1 -m 'annotated tag'
$ git tag -a anno2 anno1 -m 'another tag'
$ git cat-file -p anno1
object d4ec8b2d465de0c087d645f52ba5040586b8ce0f
type commit
tag anno1
tagger Chris Torek <[email protected]> 1413933523 -0600

annotated tag
$ git cat-file -p anno2
object cd1e0637c348e46c645819ef6de36679052b4b7f
type tag
tag anno2
tagger Chris Torek <[email protected]> 1413934239 -0600

another tag
like image 167
torek Avatar answered Nov 13 '22 15:11

torek


"peeling" refers to dereferencing, e.g. going from a ref to the annotated tag object to a ref on the commit it points to.

The term is also used for the other cases of the ^{xxx} syntax, e.g. to go from commit to tree with abc1234^{tree}.

like image 32
remram Avatar answered Nov 13 '22 15:11

remram