John John - 1 month ago 11
Git Question

How can I work out time difference between git tag and the original comit

I am looking to work out the time difference between when a commit is made and when that commit was tagged.

This is what I have so far however the committerdate which I think this is the correct field is null.

git for-each-ref --format='%(taggerdate) : %(committerdate) : %(refname)' --sort=-taggerdate --count=10 refs/tags


At a guess I am looking only at tags, though I cannot get it right. In an ideal world it would show the difference between the times however I can do this afterwards if it is not possible.

Answer

The git for-each-ref documentation is kind of misleading:

For commit and tag objects, the special creatordate and creator fields will correspond to the appropriate date or name-email-date tuple from the committer or tagger fields depending on the object type. These are intended for working on a mix of annotated and lightweight tags.

This does work exactly as documented: %(creatordate) gets the date from the tagger field of these annotated tags. However, it seems to imply that for an annotated tag, Git might inspect the corresponding commit: if not, how would it ever get the committer?

In fact, for-each-ref never looks directly at an annotated tag's target object. The mention of the committer field is specific to lightweight tags, which point to commits,1 rather than annotated tag objects. Fortunately, there's a format directive saying to "look indirectly", as it were: simply prefix the directive with *.2

Hence the answer is:

git for-each-ref \
    --format='%(taggerdate) : %(*committerdate) :  %(refname)' \
    --sort=-taggerdate --count=10 refs/tags

1Lightweight tags can point directly to trees or blobs; it's not immediately clear what happens in this case. Probably the expansion is empty.

2Note that this only indirects once, so if the target of the annotated tag is another tag (or is a tree or blob), there will be no committer date field. To really make this reliable, you probably should use a bit of shell script and resolve the tag name with the ^{} or ^{commit} suffix. (The difference between these two is that ^{commit} will fail if the ultimate target object is a tree or blob, while ^{} will succeed, finding that tree or blob object.)