Git Tags
Tag management: marking releases, versioning, and milestone snapshots.
Tag Fundamentals
# TWO TYPES OF TAGS
# Lightweight: just a pointer to a commit (like a branch that doesn't move)
# Annotated: full object with tagger, date, message, optional GPG signature
# CREATE LIGHTWEIGHT TAG
git tag v1.0 # Tag current HEAD
git tag v1.0 abc1234 # Tag specific commit
# CREATE ANNOTATED TAG (preferred for releases)
git tag -a v1.0 -m "Release 1.0" # With message
git tag -a v1.0 abc1234 -m "Release 1.0" # Tag specific commit
git tag -a v1.0 # Opens editor for message
# WHEN TO USE WHICH
# Lightweight: temporary markers, personal bookmarks, CI/CD triggers
# Annotated: releases, milestones, anything shared publicly
# Rule: if others will see it, annotate it
# LIST TAGS
git tag # All tags
git tag -l # Same
git tag -l "v1.*" # Glob pattern
git tag -l --sort=-v:refname # Sort by version (newest first)
git tag -l --sort=-creatordate # Sort by date (newest first)
# TAG DETAILS
git show v1.0 # Full tag info + commit
git tag -n # Tags with first line of message
git tag -n5 # Tags with 5 lines of message
git cat-file -t v1.0 # Show type (tag vs commit)
# CHECK IF TAG EXISTS
git tag -l "v1.0" | grep -q "v1.0" && echo "exists" || echo "not found"
git rev-parse --verify "v1.0" 2>/dev/null && echo "exists"
Tag Operations
# DELETE LOCAL TAG
git tag -d v1.0 # Delete locally
# DELETE REMOTE TAG
git push origin --delete v1.0 # Delete from remote
git push origin :refs/tags/v1.0 # Older syntax, same effect
# RENAME TAG (delete + recreate)
git tag new-tag old-tag # Copy to new name
git tag -d old-tag # Delete old local
git push origin new-tag :old-tag # Push new, delete old remote
# MOVE TAG TO DIFFERENT COMMIT
git tag -f v1.0 abc1234 # Force overwrite local
git push --force origin v1.0 # Force update remote
# WARNING: Only do this for tags nobody else has fetched
# PUSH TAGS
git push origin v1.0 # Push specific tag
git push origin --tags # Push ALL local tags
git push --follow-tags # Push commits + annotated tags only
# PULL/FETCH TAGS
git fetch --tags # Fetch all tags from origin
git fetch origin --tags # Explicit remote
git fetch --prune-tags # Remove local tags deleted on remote
# CHECKOUT TAG (detached HEAD)
git checkout v1.0 # Detached HEAD at tag
git checkout -b release-v1.0 v1.0 # Create branch from tag
# COMPARE TAGS
git diff v1.0 v2.0 # Diff between releases
git log v1.0..v2.0 --oneline # Commits between releases
git shortlog v1.0..v2.0 # Changelog between releases
Tag Workflows
# SEMANTIC VERSIONING (semver)
# Format: vMAJOR.MINOR.PATCH
# v1.0.0 → v1.0.1 (patch: bug fix)
# v1.0.0 → v1.1.0 (minor: new feature, backward compatible)
# v1.0.0 → v2.0.0 (major: breaking change)
# RELEASE WORKFLOW
git checkout main
git pull origin main # Ensure up to date
git tag -a v1.2.0 -m "Release 1.2.0: Add feature X, fix bug Y"
git push origin v1.2.0 # Push tag only
# OR
git push --follow-tags # Push commits + tags
# PRE-RELEASE TAGS
git tag -a v2.0.0-rc.1 -m "Release candidate 1"
git tag -a v2.0.0-beta.1 -m "Beta 1"
git tag -a v2.0.0-alpha.1 -m "Alpha 1"
# LIST LATEST RELEASE TAG
git describe --tags --abbrev=0 # Latest tag
git describe --tags # Latest tag + distance
# Output: v1.2.0-3-gabc1234
# v1.2.0 = last tag
# 3 = commits since tag
# gabc1234 = current commit prefix
# GENERATE CHANGELOG FROM TAGS
git log v1.0.0..v1.1.0 --oneline # Changes in v1.1.0
git log v1.0.0..v1.1.0 --pretty=format:"- %s (%h)" # Markdown bullet list
# FIND WHICH TAG CONTAINS A COMMIT
git tag --contains abc1234 # Tags that include this commit
git describe --contains abc1234 # Nearest tag after commit
# TAG-BASED CI/CD
# Many CI systems trigger on tag push:
# - GitHub Actions: on: push: tags: ['v*']
# - GitLab CI: rules: - if: $CI_COMMIT_TAG
Infrastructure Repository Tags
# DOMUS-* TAG CONVENTIONS
# Documentation repos: tag when content milestones hit
git tag -a docs-v1.0 -m "Initial documentation complete"
git tag -a docs-v1.1 -m "Added ISE troubleshooting runbooks"
# SNAPSHOT TAGS (before major changes)
git tag -a pre-restructure-2026-04 -m "Snapshot before codex restructure"
git tag -a pre-migration -m "Before Antora migration"
# TAG ALL REPOS AT MILESTONE
for repo in ~/atelier/_bibliotheca/domus-*/; do
name=$(basename "$repo")
git -C "$repo" tag -a "milestone-2026-q2" -m "Q2 2026 milestone"
git -C "$repo" push origin "milestone-2026-q2"
done
# LIST TAGS ACROSS REPOS
for repo in ~/atelier/_bibliotheca/domus-*/; do
name=$(basename "$repo")
tags=$(git -C "$repo" tag -l --sort=-creatordate | head -3)
if [[ -n "$tags" ]]; then
echo "=== $name ==="
echo "$tags"
fi
done
# CLEAN UP OLD TAGS
git tag -l "temp-*" | xargs git tag -d # Delete local temp tags
git tag -l "temp-*" | xargs -I{} git push origin --delete {} # Delete remote
Tag Gotchas
# WRONG: Pushing without --tags or --follow-tags
git push origin main
# Tags stay local! Others won't see them
# CORRECT: Push tags explicitly
git push origin v1.0 # Specific tag
git push --follow-tags # Commits + annotated tags
# WRONG: Moving a tag that others fetched
git tag -f v1.0 abc1234
git push --force origin v1.0
# Others still have old v1.0 → confusion
# CORRECT: Don't move published tags
# If you must, communicate the change and have others:
git fetch --tags --force # Force update local tags
# WRONG: Lightweight tags for releases
git tag v1.0
# No metadata, no message, no audit trail
# CORRECT: Annotated tags for anything shared
git tag -a v1.0 -m "Release 1.0: description"
# WRONG: Forgetting tags during clone
git clone repo.git
# Gets tags by default, BUT...
# EDGE CASE: Shallow clone misses tags
git clone --depth 1 repo.git
# May not have all tags
git fetch --tags --unshallow # Fix: get full history
# WRONG: Deleting tag locally but not remotely
git tag -d v1.0
# Still on remote! Others can fetch it again
# CORRECT: Delete both
git tag -d v1.0
git push origin --delete v1.0
Quick Reference
# CREATE
git tag v1.0 # Lightweight
git tag -a v1.0 -m "message" # Annotated (preferred)
git tag -a v1.0 abc1234 -m "msg" # Tag specific commit
# LIST
git tag -l "v1.*" # Glob filter
git tag -l --sort=-v:refname # Newest version first
# INSPECT
git show v1.0 # Tag details
git describe --tags # Latest tag + distance
# PUSH
git push origin v1.0 # Specific tag
git push --follow-tags # Commits + annotated tags
git push origin --tags # All tags
# DELETE
git tag -d v1.0 # Local
git push origin --delete v1.0 # Remote
# COMPARE RELEASES
git log v1.0..v2.0 --oneline # Changes between tags
git diff v1.0 v2.0 # Diff between tags
# CHECKOUT
git checkout -b release-v1.0 v1.0 # Branch from tag