Can a lightweight tag be converted to an annotated tag?

33

8

I've tagged a commit with a lightweight tag, and pushed that tag to a remote repo, shared with other developers. I have now realised I should have annotated it so that it appears in git describe.

Is there a way to convert it/re-tag the commit without breaking things?

Stuart K

Posted 2011-02-15T10:34:25.703

Reputation: 2 283

Answers

29

A lightweight tag is just a 'ref' that points at that commit. You can force-create a new annotated tag on top of the old tag:

git tag -a -f <tagname> <tagname>

As of Git v1.8.2, you need to use --force to replace any tags on a remote with git push, even if you are replacing a lightweight tag with something that is effectively a fast-forward or a true tag object pointing at the same commit as the existing tag reference.

git push --force origin <tagname>

CB Bailey

Posted 2011-02-15T10:34:25.703

Reputation: 503 773

3But won't this use a confusing date? – SamB – 2014-01-09T19:06:49.773

1Also, are there any implications for developers that already pulled the original lightweight tag? Will those developers see the annotation to the new tag after they've pulled again, or do they need to do something special (like deleting their local tag) before? – sschuberth – 2015-07-23T10:23:21.207

Doesn't seem to work: hint: Updates were rejected because the tag already exists in the remote. I think you really do have to delete the tag first. – Zac Thompson – 2016-05-20T22:19:41.140

1@ZacThompson: This changed in v1.8.2 (March 2013) – CB Bailey – 2016-05-20T23:47:41.450

3If you'd rather not have tags tagging tags, do git tag -a -f &lt;tagname&gt; &lt;tagname&gt;^0 instead. Otherwise you create a new reference to your old tag instead of the stolen refs/tags/&lt;tagname&gt;, excluding it from garbage collection. – Ferenc Wágner – 2016-07-21T14:56:12.590

20

Based on Charles' answer and on this blog post, I think it is better to use something like this:

#!/bin/sh
tag=$1
date="$(git show $tag --format=%aD | head -1)"
GIT_COMMITTER_DATE="$date" git tag -a -f $tag $tag

SamB

Posted 2011-02-15T10:34:25.703

Reputation: 6 578

2Nice :) Instead of | head -1 you can use -s or --no-patch. And maybe using the committer date (%cD) (and also their name, %cn, as GIT_COMMITER_NAME) might be desirable. – Tobias Kienzler – 2017-02-10T09:49:36.107

2

You can also simply use git describe --tags to also include lightweight tags in the search.

Claudio

Posted 2011-02-15T10:34:25.703

Reputation: 2 632

1

Convert all tags to annotated (based on Charles Bailey's example and Ferenc Wágner's comment):

for tag in $(git tag -l); do git tag -a -f $tag $tag^0 -m $tag; done
git push --tags --force

Stanislav German-Evtushenko

Posted 2011-02-15T10:34:25.703

Reputation: 361