← Git

Workflows & Best Practices

What are tags in Git, and what is the difference between an annotated tag and a lightweight one?

Show answer — try answering out loud first

A tag is a label that marks a specific commit, usually to point to a version (release), like v1.0.0. A lightweight tag is just a pointer to the commit, with no extra data. An annotated tag additionally stores author, date, and message, and is the recommended one for releases. They usually follow Semantic Versioning (MAJOR.MINOR.PATCH).

Unlike a branch, a tag does not move: it marks a fixed point in history, typically "this is where we released version X."

  • Lightweight tag: a simple name that points to a commit. Lightweight, with no metadata. Useful for private or temporary marks.
  • Annotated tag: a complete object in Git, with author, date, message (and optionally a signature). It's the recommended one for official releases, because it documents who created it and when.

Semantic Versioning (semver): MAJOR.MINOR.PATCH (e.g. 2.4.1):

  • MAJOR: incompatible changes.
  • MINOR: new backward-compatible functionality.
  • PATCH: backward-compatible fixes.
# ANNOTATED tag (recommended for releases): with -a and a message via -m
git tag -a v1.0.0 -m "Primera version estable"

# LIGHTWEIGHT tag: just the name, no metadata
git tag v1.0.0-beta

# List all tags
git tag
# v1.0.0
# v1.0.0-beta

# View information about an annotated tag (author, date, message)
git show v1.0.0

# Tag an old commit (by its hash)
git tag -a v0.9.0 1a2b3c4 -m "Version previa"

# Tags are NOT pushed with a normal push: you must push them separately
git push origin v1.0.0
# or all at once:
git push origin --tags

Believing that git push pushes tags automatically. It doesn't: you must push them explicitly with git push origin <tag> or git push --tags. Another mistake is using lightweight tags for official releases, when the recommendation is annotated ones (with -a) so that the author, date, and reason are recorded.

"A tag is a fixed label that marks a specific commit, usually to point to a version, like v1.0.0. Unlike a branch, a tag doesn't move. There are two kinds: the lightweight one, which is just a pointer, and the annotated one, which stores author, date, and message, and is the recommended one for releases. I usually name them following semantic versioning, with MAJOR.MINOR.PATCH. And I remember that tags aren't pushed with a normal push: you have to run git push origin --tags."

Quick challenge

You created git tag -a v1.0.0 -m "release" and then ran git push. Your teammate doesn't see the tag on GitHub. Why?

See answer

Because plain git push does not push tags: it only pushes the branch's commits. Tags must be sent separately with git push origin v1.0.0 (for a specific one) or git push origin --tags (for all of them). That's why your teammate doesn't see it yet.