Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deleted Git tags restore themselves

We recently ran into an issue with tags in our Git repository.

We deleted our tags locally and remotely, yet they kept restoring itself every time we either push to or fetch from remote.

We are currently working in a team of three and when we think we actually got rid of the tags, someone would do a push and we all get them again.

We all tried:

git tag -d 12345
git push origin :refs/tags/12345

Anyone else ran into this issue?

like image 428
David C. Avatar asked Feb 22 '16 22:02

David C.


People also ask

What happens if you delete a git tag?

By omitting the source ref (the part before the colon), you push 'nothing' to the destination, deleting the ref on the remote end. It is also interesting to know that git tag -d `git tag` will delete all local tags.

Does deleting a git tag delete the commits?

You do not remove commits. You remove pointers to commits and if commits are no longer referenced git will garbage collect them some day (depending on your configuration).

Are git tags permanent?

The most common style is to use annotated tags for permanent tags, things which you expect to push and you expect other people to look at. Lightweight tags are then used for temporary tags, things which you will not push and which you do not want other people to see.

Can you reuse git tags?

Git tags can't be reused. A tag can be removed and reassigned.


2 Answers

A handy way to solve this problem for all tags at once :

1) To be done ONCE, from any one of the local repos

git push <remoteName> :<tagToDelete>
# (for example) git push origin :tag_foo_bar

2) Then, to be done from EACH local repo involved

git tag -d `git tag -d` && git fetch -t

This will list then delete all local copies of the repo's tags, then get them back anew from the remote.

like image 65
Romain Valeri Avatar answered Oct 31 '22 08:10

Romain Valeri


Delete the tags again and then do this:

# verify that the tag was removed form another computer
git fetch --all --prune

Important

If you are on an older version of git <2.0 git push without branch name might push all your branches & tags to the remote. Verify that this is not the case here.


What else can you try?

# push just the tag name without refs/tags/...
git push origin :tagname

# same as above but with the `--delete` flag instead of `:`
git push --delete origin tagname

# as you already did locally - delete the tag as well
git tag -d tagname

Git hooks

Verify that there are no git hooks which block you from delete the tags.
Here is a sample hook which do it:

#!/bin/sh

log() { printf '%s\n' "$*"; }
error() { log "ERROR: $*" >&2; }
fatal() { error "$*"; exit 1; }

case $1 in
    refs/tags/*)
        [ "$3" != 0000000000000000000000000000000000000000 ] \
            || fatal "you're not allowed to delete tags"
        [ "$2" = 0000000000000000000000000000000000000000 ] \
            || fatal "you're not allowed to move tags"
        ;;

    # personal touch :-)
    echo "                                         "
    echo "                   |ZZzzz                "
    echo "                   |                     "
    echo "                   |                     "
    echo "      |ZZzzz      /^\            |ZZzzz  "
    echo "      |          |~~~|           |       "
    echo "      |        |-     -|        / \      "
    echo "     /^\       |[]+    |       |^^^|     "
    echo "  |^^^^^^^|    |    +[]|       |   |     "
    echo "  |    +[]|/\/\/\/\^/\/\/\/\/|^^^^^^^|   "
    echo "  |+[]+   |~~~~~~~~~~~~~~~~~~|    +[]|   "
    echo "  |       |  []   /^\   []   |+[]+   |   "
    echo "  |   +[]+|  []  || ||  []   |   +[]+|   "
    echo "  |[]+    |      || ||       |[]+    |   "
    echo "  |_______|------------------|_______|   "
    echo "                                         "
    echo "                                         "
    echo "      This is your last time trying to   " 
    echo "      delete or to move our tags. :-)    "
    echo "                                         "

esac

Git v2.0 Release Notes

Backward compatibility notes

When git push [$there] does not say what to push, we have used the traditional matching semantics so far (all your branches were sent to the remote as long as there already are branches of the same name over there). In Git 2.0, the default is now the simple semantics, which pushes:

  • only the current branch to the branch with the same name, and only when the current branch is set to integrate with that remote branch, if you are pushing to the same remote as you fetch from; or

  • only the current branch to the branch with the same name, if you are pushing to a remote that is not where you usually fetch from.

You can use the configuration variable push.default to change this. If you are an old-timer who wants to keep using the matching semantics, you can set the variable to matching, for example. Read the documentation for other possibilities.

like image 35
CodeWizard Avatar answered Oct 31 '22 10:10

CodeWizard