What is the difference between a lightweight tag and an annotated tag, and which should you use for releases?
Take a moment.
Say your answer out loud or write it down first — retrieval is what makes it stick. Reveal when you're ready.
Short answer
A lightweight tag is just a named pointer to a commit — a bookmark. An annotated tag is a full Git object storing a message, the tagger name and email, and the date. Use annotated tags for releases: they are checksummed, carry release notes, can be signed with GPG, and tools like git describe and release automation rely on them.
Detailed explanation
git tag v1.2.0 creates a lightweight tag — a ref in refs/tags/ pointing at a commit, with no metadata. git tag -a v1.2.0 -m 'Release notes' creates an annotated tag, a real object with author, date, and message. The practical differences: git show on an annotated tag displays the message; git tag -v can verify a GCP signature (only possible on annotated tags); git describe prefers annotated tags when computing version strings; and release tooling (semantic-release, GitHub Release automation) reads annotated tag messages to build changelogs. Lightweight tags suit private bookmarks; annotated tags are the standard for anything published. For releases, go further: sign with git tag -s (or -u <key>) so consumers can verify provenance, and push tags explicitly (git push --tags or better, push the release tag only). Tag the merge commit on main, not a feature-branch commit, so the tag reflects what shipped.
Example
# Annotated release tag with message:
git tag -a v1.2.0 -m 'v1.2.0 — cursor pagination, export CSV'
# Signed tag (verifiable provenance):
git tag -s v1.2.0 -m 'v1.2.0 release'
git tag -v v1.2.0 # verify signature
# Push the release tag:
git push origin v1.2.0
# Release automation reads it:
git describe --tags # => v1.2.0Interview tip
Give the bookmark-versus-object distinction, then immediately say 'annotated for releases' and list why — message, GPG signing, git describe, and changelog tooling. One line each.
Common mistakes
- Using lightweight tags for releases and losing metadata.
- Forgetting to push tags — commits go with
git push, tags needgit push --tags. - Tagging a feature-branch commit instead of the merge commit on main.