Git & GitHub

Working with Tags

13 min Lesson 16 of 35

Working with Tags

Tags in Git are references that point to specific commits in your repository history. They are typically used to mark release points (v1.0, v2.0, etc.) and capture important milestones in your project. Unlike branches, tags don't change - they permanently mark a specific point in time.

Understanding Tags

Git supports two types of tags:

Lightweight Tags: - Simple pointer to a commit - Just a name for a commit hash - No additional information stored - Like a bookmark Annotated Tags: - Full objects in Git database - Contains tagger name, email, and date - Can include a message - Can be signed and verified with GPG - Recommended for releases
Best Practice: Always use annotated tags for releases and public version markers. Use lightweight tags for temporary markers or personal use only.

Creating Lightweight Tags

Creating a lightweight tag is simple - just provide a tag name:

# Create a lightweight tag at current commit git tag v1.0.0 # Create a lightweight tag at specific commit git tag v0.9.0 abc1234 # View the tag git show v1.0.0

Lightweight tags are just pointers - no additional metadata is stored.

Creating Annotated Tags

Annotated tags are more comprehensive and recommended for releases:

# Create annotated tag with message git tag -a v1.0.0 -m "Release version 1.0.0" # Create annotated tag with editor for longer message git tag -a v1.0.0 # Tag a specific commit git tag -a v0.9.0 abc1234 -m "Beta release" # View detailed tag information git show v1.0.0

When you view an annotated tag with git show, you'll see the tagger information, date, message, and commit details.

Note: Annotated tags include the tagger's name, email, timestamp, and a tagging message. This makes them ideal for marking official releases.

Semantic Versioning

The most common convention for version tags is Semantic Versioning (SemVer):

Format: MAJOR.MINOR.PATCH v1.0.0 - Initial stable release v1.0.1 - Patch: Bug fixes (backward compatible) v1.1.0 - Minor: New features (backward compatible) v2.0.0 - Major: Breaking changes (not backward compatible) Examples: git tag -a v1.0.0 -m "First stable release" git tag -a v1.0.1 -m "Fix critical security bug" git tag -a v1.1.0 -m "Add user authentication feature" git tag -a v2.0.0 -m "Complete API redesign"
Tip: Prefix tags with "v" (v1.0.0) rather than just numbers (1.0.0). This is the industry standard and helps distinguish version tags from other numeric identifiers.

Listing Tags

Git provides several ways to view your tags:

# List all tags git tag # List tags matching a pattern git tag -l "v1.*" git tag -l "v2.0.*" # Show tag details (annotated tags only) git tag -n git tag -n5 # Show first 5 lines of message # Show detailed information about a specific tag git show v1.0.0

Pushing Tags to Remote

By default, git push does NOT push tags to remote repositories. You must push them explicitly:

# Push a single tag git push origin v1.0.0 # Push all tags at once git push origin --tags # Push all tags (including lightweight) git push origin --tags # Push only annotated tags git push origin --follow-tags
Warning: git push --tags pushes ALL tags (lightweight and annotated). Use --follow-tags to push only annotated tags automatically with commits.

Checking Out Tags

You can view your code at a specific tag, but this puts you in "detached HEAD" state:

# Checkout a tag (detached HEAD state) git checkout v1.0.0 # Create a new branch from a tag git checkout -b hotfix-branch v1.0.0 # View files at a specific tag without checking out git show v1.0.0:path/to/file.txt
Detached HEAD: When you checkout a tag, you're not on any branch. Any commits you make won't belong to a branch and could be lost. Always create a new branch if you want to make changes from a tagged point.

Deleting Tags

Sometimes you need to remove tags (typos, wrong version, etc.):

# Delete local tag git tag -d v1.0.0 # Delete remote tag (two methods) git push origin --delete v1.0.0 git push origin :refs/tags/v1.0.0 # Delete multiple tags git tag -d v1.0.0 v1.0.1 v1.0.2
Important: If you delete and recreate a tag with the same name, it can cause confusion for other developers. Communicate with your team before modifying published tags.

Practical Release Workflow

Here's a typical workflow for creating a release with tags:

# 1. Ensure you're on the main branch and it's up to date git checkout main git pull origin main # 2. Make sure all tests pass and code is ready # Run your test suite here # 3. Update version numbers in your code (package.json, etc.) # Edit files as needed # 4. Commit version bump git add . git commit -m "Bump version to 1.2.0" # 5. Create annotated tag git tag -a v1.2.0 -m "Release version 1.2.0 New features: - Added user dashboard - Improved performance - Fixed critical bugs" # 6. Push commits and tag git push origin main git push origin v1.2.0 # 7. Create release notes on GitHub (optional)

Advanced Tag Operations

Some advanced scenarios you might encounter:

# Tag a specific file state (not recommended, but possible) git tag snapshot-config abc1234 path/to/config.php # Find which tag contains a commit git tag --contains abc1234 # Find tags reachable from a commit git describe --tags # List tags sorted by version git tag --sort=v:refname # List tags sorted by date git tag --sort=-creatordate

Comparing Tags

You can compare different versions of your code using tags:

# Show differences between two tags git diff v1.0.0 v1.1.0 # Show log between two tags git log v1.0.0..v1.1.0 # Show files changed between tags git diff --name-only v1.0.0 v1.1.0 # Generate changelog between tags git log v1.0.0..v1.1.0 --oneline --no-merges

Practice Exercise:

Create a release workflow:

  1. Create a new repository or use an existing one
  2. Make several commits to simulate development
  3. Create an annotated tag v1.0.0 for your first release
  4. Make more commits with new features
  5. Create tag v1.1.0
  6. List all tags and view their details
  7. Compare the differences between v1.0.0 and v1.1.0
  8. Practice pushing tags to a remote repository

Commands to use:

git tag -a v1.0.0 -m "First stable release"
git tag -a v1.1.0 -m "Added new features"
git tag
git show v1.0.0
git diff v1.0.0 v1.1.0
git push origin --tags

Common Tag Mistakes

❌ Using lightweight tags for releases git tag v1.0.0 ✓ Use annotated tags instead git tag -a v1.0.0 -m "Release 1.0.0" ❌ Forgetting to push tags git push origin main ✓ Push tags explicitly git push origin v1.0.0 ❌ Tagging without testing git tag -a v1.0.0 -m "Release" ✓ Test thoroughly first # Run tests, verify everything works git tag -a v1.0.0 -m "Release"

Summary

In this lesson, you learned:

  • Tags mark specific points in Git history, typically for releases
  • Lightweight tags are simple pointers; annotated tags include metadata
  • Use Semantic Versioning (MAJOR.MINOR.PATCH) for version numbers
  • Tags must be pushed explicitly to remote repositories
  • Checking out tags puts you in detached HEAD state
  • Annotated tags are recommended for all public releases
  • Tags can be compared to see changes between versions
Next Up: In the next lesson, we'll learn about stashing changes - a powerful feature for temporarily storing work without committing!