Tagging releases

Git · Practical · 7 min

Tags give permanent, human-readable names to the exact commits you shipped.

A tag is a name for a specific commit that, unlike a branch, does not move. Tags mark releases (v2.4.0), so you can always check out, diff against or rebuild exactly what shipped.

There are two kinds:

  • Lightweight (git tag v1.0): just a ref pointing at a commit, like a branch that never moves.
  • Annotated (git tag -a v1.0 -m "Release 1.0"): a full object with tagger, date and message, and optionally a GPG/SSH signature (-s). Use annotated tags for releases; tools like git describe and many release pipelines expect them.

Tags are not pushed by default. Push one with git push origin v1.0, all with git push --tags, or set push.followTags true so git push also sends annotated tags reachable from the commits you push.

Other commands:

  • git tag -l "v2.*": list matching tags.
  • git show v1.0: the tag message and the commit.
  • git tag -a v0.9 3f9a2c1 -m "...": tag an older commit.
  • git tag -d v1.0 then git push origin --delete v1.0: delete locally and remotely.

git describe names any commit relative to the nearest annotated tag, for example v2.4.0-12-g9c1e2ab = 12 commits after v2.4.0, at commit 9c1e2ab. Many build scripts embed this as the version string.

Treat published tags as immutable. Moving a release tag after people have fetched it leads to confusing mismatches; make a new version instead.

Example

git tag -a v2.4.0 -m "Release 2.4.0"
git push origin v2.4.0
git config --global push.followTags true   # push annotated tags with commits

git tag -l "v2.*"           # v2.3.0  v2.4.0
git describe                # v2.4.0-12-g9c1e2ab
git switch --detach v2.3.0  # look at an old release
git diff v2.3.0 v2.4.0 --stat

Remember

  • Tags are fixed names for commits; branches move, tags don't
  • Use annotated tags (-a or -s) for releases
  • Tags aren't pushed by default: push them or enable push.followTags
  • Don't move published tags; release a new version

Watch out for

  • Tagging locally and forgetting to push the tag, so CI never sees the release.

Check yourself

  1. You created tag v1.2 and ran git push. Does the remote have the tag?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: git-scm.com/book/en/v2/Git-Basics-Tagging