← Back to DevBytes

Git Tagging and Releases

What is Git Tagging?

In Git, a tag is a reference point that marks a specific commit in your repository's history. Think of it as a sticky note you attach to a particular snapshot of your codebase. While branches move forward as you commit, tags remain fixed — they are immutable pointers that permanently identify a moment in time.

Tags are most commonly used to mark release versions (like v1.0.0, v2.1.3) but can also denote any significant milestone, such as a stable build, a deployment candidate, or the exact commit that passed QA.

Why Tagging Matters for Releases

🚀 Deploy your AI agent in 10 minutes

Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.

Try it free →

Tagging is the backbone of a disciplined release workflow. Here's why it matters:

Types of Git Tags: Lightweight vs Annotated

Git offers two distinct kinds of tags, and understanding the difference is crucial for a professional workflow.

Lightweight Tags

A lightweight tag is simply a pointer to a commit — nothing more. It stores no extra metadata and acts like a branch that never moves. Use these for quick, personal markers or temporary bookmarks where no additional context is needed.

# Create a lightweight tag
git tag v1.0.0-light

# See what it points to
git show v1.0.0-light

The output will just show the commit object. There's no tagger name, date, or message.

Annotated Tags

Annotated tags are full objects in Git's database. They carry metadata: the tagger's name and email, a creation timestamp, a message, and can optionally be GPG-signed. These are the standard for public releases because they provide a complete, verifiable record.

# Create an annotated tag with a message
git tag -a v1.0.0 -m "Release version 1.0.0: stable core with new auth module"

# Show full details including tagger and message
git show v1.0.0

The output includes the tagger information, the date the tag was created, and the full annotation message you provided — a rich historical record that lightweight tags simply lack.

How to Create and Manage Tags

Here's a comprehensive walkthrough of everyday tag operations.

Creating a Tag on the Current Commit

# Annotated tag (recommended for releases)
git tag -a v1.2.0 -m "Beta release of v1.2 with experimental search"

# Lightweight tag (quick bookmark)
git tag pre-release-checkpoint

Tagging a Past Commit

Tags aren't limited to HEAD. You can tag any commit in history by referencing its hash.

# Find the commit hash you want to tag
git log --oneline

# Example output:
# 9fceb02 Add payment integration
# 5a3c71e Fix login bug
# e4b2d90 Initial prototype

# Tag the commit that fixed the login bug
git tag -a v0.9.1-hotfix 5a3c71e -m "Hotfix for login issue shipped to production"

Listing and Filtering Tags

# List all tags alphabetically
git tag

# List tags matching a pattern (wildcard)
git tag -l "v1.*"

# List tags with their full annotations
git tag -l --format='%(refname:short) %(taggerdate) %(subject)'

# List tags sorted by version (if you use semantic versioning)
git tag --sort=-version:refname

Pushing Tags to a Remote

By default, git push does not send tags to the remote. You must explicitly push them.

# Push a single tag
git push origin v1.2.0

# Push all tags at once
git push origin --tags

# Push annotated tags only (safer — avoids pushing accidental lightweight tags)
git push origin --follow-tags

Checking Out a Tag

Tags are read-only pointers. Checking one out puts you in a detached HEAD state — perfect for inspecting, building, or branching off a historical release.

# Check out a tag for inspection or building
git checkout v1.0.0

# Create a new branch from a tag if you need to make changes
git checkout -b hotfix-from-v1.0.0 v1.0.0

Deleting Tags

# Delete a local tag
git tag -d v1.0.0

# Delete a tag from the remote as well
git push origin --delete v1.0.0

# Delete a remote tag using the older ref syntax
git push origin :refs/tags/v1.0.0

Semantic Versioning with Tags

Most modern projects pair Git tags with Semantic Versioning (SemVer). The format is MAJOR.MINOR.PATCH:

# Examples of semantic version tags
git tag -a v1.0.0 -m "Initial stable release"
git tag -a v1.1.0 -m "Added user profiles feature"
git tag -a v1.1.1 -m "Patched token expiration bug"
git tag -a v2.0.0 -m "Breaking: redesigned API authentication"

A pre-release suffix (like -alpha, -beta, -rc.1) can be appended for early candidates:

git tag -a v2.0.0-beta.1 -m "First beta for v2 rewrite"
git tag -a v2.0.0-rc.2 -m "Release candidate 2 — all known blockers resolved"

Signing Tags with GPG

For security-critical projects, you can cryptographically sign annotated tags so consumers can verify the tag was created by you and hasn't been tampered with.

# Create a signed tag (requires GPG key setup)
git tag -s v1.0.0 -m "Signed release: verified integrity"

# Verify a signed tag
git tag -v v1.0.0

If you use GitHub, signed tags display a green "Verified" badge in the UI, building trust with users who pull your releases.

GitHub and GitLab Releases

Platforms like GitHub and GitLab build a dedicated Release feature on top of Git tags. A Release associates a tag with rich metadata: release notes, binaries (assets), and changelog links. Creating one is straightforward via the CLI tools or the web UI.

Creating a GitHub Release with the CLI

# Using GitHub CLI (gh) — first create the tag, then the release
git tag -a v1.3.0 -m "New dashboard and reporting module"
git push origin v1.3.0

# Create a release from the tag with release notes
gh release create v1.3.0 \
  --title "v1.3.0: Dashboard & Reporting" \
  --notes "## New Features
- Interactive analytics dashboard
- PDF report generation
- Scheduled report emails" \
  --generate-notes

Attaching Build Artifacts

# Upload compiled binaries or packages as release assets
gh release upload v1.3.0 \
  ./dist/myapp-linux-amd64 \
  ./dist/myapp-darwin-amd64 \
  ./dist/myapp-windows-amd64.exe

This workflow turns a simple Git tag into a full-fledged software distribution point that users can download from.

Best Practices for Git Tagging and Releases

Conclusion

Git tags are deceptively simple yet profoundly powerful. A well-maintained tagging practice transforms your repository from a pile of commits into a structured, navigable release history. By combining annotated tags, semantic versioning, and platform release features, you create a workflow where every shipped version is traceable, reproducible, and verifiable. The small discipline of tagging each release with intention pays compounding dividends: smoother CI/CD pipelines, happier consumers pinning to your versions, and a codebase history that tells a clear, professional story.

🚀 Need a reliable AI agent for your project?

Deploy Hermes Agent in 10 minutes. Managed hosting, zero DevOps.

Get Started — $23.99/mo
← Back to all articles