Git Tagging

Git tags mark a specific commit with a permanent, human-readable label, most commonly used to record release points like v1.0.0.

Why Tag Instead of Just Remembering a Commit Hash

Commit hashes are precise but unmemorable. A tag gives a fixed name — like v2.3.0 or release-2026-07 — to a single commit, so anyone can check out, compare against, or build from that exact point in history using a name instead of a 40-character hash. Unlike branches, tags don't move: once created, a tag always points at the same commit even as the branch it was made from keeps advancing.

Lightweight Tags

A lightweight tag is just a named pointer to a commit — essentially a bookmark with no extra metadata of its own. It's created by passing the tag name to git tag with no other flags. These are quick, but they don't record who created the tag, when, or why.

Create and list a lightweight tag

$ git tag build-2026-07-16
$ git tag
build-2026-07-16
v1.0.0
v1.1.0

$ git show build-2026-07-16
commit 8b1f5c9a2e4d0c...
Author: Priya Shah <priya@example.com>
Date:   Thu Jul 16 09:12:44 2026 +0530

    Fix bug in header render

Annotated Tags

An annotated tag is a full object in Git's database: it stores the tagger's name and email, the date, an optional message, and can even be GPG-signed. This is the recommended form for anything you'd call a release, because git show on an annotated tag displays the tag's own metadata before the commit it points to, giving a clear record of intent.

Create an annotated tag with a message

$ git tag -a v1.2.0 -m "Release 1.2.0: adds checkout redesign"
$ git show v1.2.0
tag v1.2.0
Tagger: Priya Shah <priya@example.com>
Date:   Thu Jul 16 09:20:11 2026 +0530

Release 1.2.0: adds checkout redesign

commit 9c0b7a41f3e28d...
Author: Priya Shah <priya@example.com>
Date:   Wed Jul 15 18:04:02 2026 +0530

    Add pagination to results list

Tagging a Past Commit

Tags don't have to point at HEAD. Pass a commit hash after the tag name (and message flags, for annotated tags) to mark an earlier point in history — useful when you forgot to tag a release at the time it happened.

Tag an older commit retroactively

$ git log --oneline -4
9c0b7a4 (HEAD -> main) Add pagination to results list
e281c99 Add loading skeleton
3fa8c21 Fix typo in header
b0a1f22 Initial release commit

$ git tag -a v1.0.0 -m "Initial public release" b0a1f22
$ git tag
v1.0.0
  • git tag <name> — create a lightweight tag on the current commit
  • git tag -a <name> -m "message" — create an annotated tag with metadata
  • git tag -a <name> <commit> -m "message" — tag a past commit retroactively
  • git tag -l "v1.*" — list tags matching a pattern
  • git tag -d <name> — delete a local tag
  • git push origin <name> — push a single tag to the remote
  • git push origin --tags — push every local tag that isn't already on the remote
  • git push origin --delete <name> — delete a tag from the remote
Note: Tags are not pushed automatically by a plain git push. If you create a tag and forget to push it explicitly, teammates and CI/CD pipelines that trigger off tags will never see it.
Note: Because tags are meant to be permanent markers, avoid moving or reusing one once it's been pushed and possibly consumed by a deploy pipeline. If you must repoint a tag, delete it locally and remotely first, then recreate it, and let anyone relying on it know.

Lightweight vs Annotated

AspectLightweight tagAnnotated tag
Stores tagger, date, messageNoYes
Can be GPG-signedNoYes
Git object typeJust a ref to a commitIts own tag object in the database
git describe outputUses it, but less informativePreferred, richer output
Recommended for releasesNoYes

A simple convention that works well: use annotated tags for anything that counts as a release or a deploy marker, and reserve lightweight tags for personal, throwaway bookmarks you don't intend to share or rely on for tooling.

Exercise: Git Tagging

What is the main difference between a lightweight tag and an annotated tag?