Question: How can I lock an existing git tag?

The purpose is to make a release tag unmovable, and to prevent somebody else from deleting a release tag in remote repository. I have tried `git tag -a tag_name`, but the tag is still deleted.

Answer: 
Within a (local) repository, nothing is protected against deletion. You can delete pretty much anything: branches, commits, and tags. You could even just delete the whole repository by simply deleting the folder. There is nothing in Git that could or even attempts to prevent this. After all, it’s *your* repository, so you can do whatever you want with it.

It’s a bit different once you add a remote repository to that equation. Again, a local repository cannot prevent you from deleting stuff on the remote repository (and you wouldn’t want the local one to be responsible for protecting the remote anyway). So Git allows you to push anything, even if that means that the remote repository does lose some information (either by actively removing things or by overwriting it with something else).

The remote repository on its own also has no protection. Git itself does not have any access management in its remote repository interaction protocols. So what you need is a third party reponsible for this stuff. For self-hosted repositories, [Gitolite](http://gitolite.com/gitolite/index.html) is pretty much *the* solution. It supports a very fine-grained permission model, and you can add rules and exceptions for almost every use case. In particular, it allows you to protect branches and tags from (harmful) modifications.

If you are not self-hosted, then you need to look for protection options with your provider. GitHub for example supports protected *branches* which allows you to prevent force-pushes on those branches. Unfortunately, it does not have the feature for tags, so you could still force-push tags. BitBucket has a more flexible feature for branch permissions which also allows patterns. It’s possible that you can use the pattern to specify tags, but I’m honestly not sure about it.

In general though, you cannot really protect your repository from having tags deleted. If it is any help, if you ever notice tags were changed or deleted, you can always force-push your local tags back in, to reset the state to how it was.
If you have a shared central repo, you can set up a `pre-receive` hook on this central repo to reject any push that would modify an already existing tag.

If you use some active git server (e.g : `gitolite`) you can enforce this kind of rule in the access rights each user has.