Skip to main content

Git Tags and GitHub Releases

What are Git Tags?

Tags are references to specific points in a repository's history. They're commonly used to mark release versions.

Two types of tags:

  • Lightweight tags: Simple pointers to commits
  • Annotated tags: Full objects with metadata (recommended for releases)

Creating Tags

Lightweight Tag

Create lightweight tag
git tag v1.0.0

This creates a tag pointing to the current commit.

Annotated Tag

Create annotated tag
git tag -a v1.0.0 -m "Release version 1.0.0"

Annotated tags include:

  • Tagger name and email
  • Tagging date
  • Message describing the release

Tag Specific Commit

Tag a past commit
git tag -a v1.0.0 <commit-hash> -m "Release version 1.0.0"

Viewing Tags

List all tags
git tag
List tags matching pattern
git tag -l "v1.*"
# Output: v1.0.0, v1.1.0, v1.2.0
Show tag details
git show v1.0.0

Shows who created the tag, when, and the tagged commit.

Semantic Versioning

Follow semantic versioning format: MAJOR.MINOR.PATCH

  • MAJOR (1.0.0): Incompatible API changes
  • MINOR (1.1.0): New features, backward compatible
  • PATCH (1.0.1): Bug fixes

Examples

v0.1.0 // Initial release
v1.0.0 // First production release
v1.1.0 // New features added
v1.1.1 // Bug fix
v2.0.0 // Breaking changes
v1.0.0-rc.1 // Release candidate
v1.0.0-beta.1 // Beta version

Pushing Tags

Push Single Tag

Push specific tag
git push origin v1.0.0

Push All Tags

Push all tags to remote
git push origin --tags

Push Tags and Commits

Push everything
git push origin main --tags

Deleting Tags

Delete Local Tag

Delete local tag
git tag -d v1.0.0

Delete Remote Tag

Delete tag on remote
git push origin --delete v1.0.0
# or
git push origin :v1.0.0

GitHub Releases

A release is a GitHub feature built on top of tags. It adds release notes, assets, and downloadable packages.

Create Release via GitHub Web UI

  1. Go to repository → Releases → "Create a new release"
  2. Select a tag or create a new one
  3. Add release title and description
  4. (Optional) Upload binary files, source code, etc.
  5. Mark as pre-release if needed
  6. Publish release

Create Release via CLI

Create release with gh CLI
gh release create v1.0.0 --title "Version 1.0.0" --notes "New features and bug fixes"
Create release with file uploads
gh release create v1.0.0 \
--title "Version 1.0.0" \
--notes "Release notes here" \
dist/app.zip \
dist/app.exe

Release Workflow

Complete Release Process

Complete release workflow
# 1. Make sure main branch is up-to-date
git checkout main
git pull origin main

# 2. Update version in package.json
vim package.json
# Change "version": "1.0.0"

# 3. Create a release commit
git add package.json
git commit -m "Release: version 1.0.0"

# 4. Create annotated tag
git tag -a v1.0.0 -m "Release version 1.0.0

## What's New
- Feature 1
- Feature 2
- Bug fixes"

# 5. Push commit and tag
git push origin main
git push origin v1.0.0

# 6. Create GitHub release
gh release create v1.0.0 --title "Version 1.0.0" --notes-file RELEASE_NOTES.md

Release Notes Best Practices

RELEASE_NOTES.md template
# Version 1.0.0

## 🎉 New Features
- User authentication system
- Dashboard redesign
- Advanced search capabilities

## 🔧 Improvements
- Performance optimization (50% faster)
- Better error messages
- Improved documentation

## 🐛 Bug Fixes
- Fixed login redirect issue
- Fixed memory leak in data processor
- Resolved race condition in cache

## 🚨 Breaking Changes
- Removed deprecated API endpoints
- Changed database schema format

## 📦 Dependencies
- Updated React to v18.0.0
- Updated Express to v4.18.0

## ⚠️ Known Issues
- Large file uploads may timeout (working on fix)
- Dark mode not supported on older browsers

## 🙏 Credits
Thanks to [@contributor1](link) and [@contributor2](link) for their contributions!

Pre-release and Beta Versions

Create pre-release version
git tag -a v2.0.0-beta.1 -m "Beta release for v2.0.0"

git tag -a v2.0.0-rc.1 -m "Release candidate 1"
Mark as pre-release on GitHub
gh release create v2.0.0-beta.1 \
--title "v2.0.0 Beta 1" \
--prerelease \
--notes "Testing phase for v2.0.0"

Automated Versioning

Using tools to automate version bumping:

Using semantic-release (npm)
npm install --save-dev semantic-release

Automatically:

  • Analyzes commits (conventional commits)
  • Determines version bump (major/minor/patch)
  • Updates version in package.json
  • Creates tag and release
  • Publishes to npm

Conventional Commits

Structure commits for automation:

feat: add user authentication
fix: resolve login redirect bug
docs: update API documentation
chore: update dependencies
perf: optimize database queries

Git Tag Aliases

Create shortcuts in .gitconfig:

Set up git aliases
git config --global alias.tag-release '!git tag -a $1 -m "Release $1"'
git config --global alias.release '!git push origin main && git push origin --tags'

Usage:

git tag-release v1.0.0
git release

Comparing Versions

Compare two tags
git diff v1.0.0 v1.1.0
See logs between tags
git log v1.0.0..v1.1.0 --oneline
Count commits between versions
git log v1.0.0..v1.1.0 --oneline | wc -l

Real-World Example

Complete release example
#!/bin/bash
# release.sh - Automated release script

VERSION=$1
BRANCH="main"

if [ -z "$VERSION" ]; then
echo "Usage: ./release.sh <version>"
exit 1
fi

# Validate version format
if ! [[ $VERSION =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Invalid version format. Use: v1.0.0"
exit 1
fi

# Update to latest main
git checkout $BRANCH
git pull origin $BRANCH

# Update package.json version
CLEAN_VERSION=${VERSION:1} # Remove 'v' prefix
npm version $CLEAN_VERSION

# Create annotated tag
git tag -a $VERSION -m "Release $VERSION"

# Push to remote
git push origin $BRANCH
git push origin $VERSION

# Create GitHub release
gh release create $VERSION \
--title "Release $VERSION" \
--notes "See CHANGELOG.md for details"

echo "✅ Release $VERSION complete!"

Downstream: Using Released Versions

Install from Specific Tag

Clone specific tag
git clone --branch v1.0.0 https://github.com/user/repo.git

Download Release Assets

Download release asset
gh release download v1.0.0 --pattern "*.zip"

Best Practices

  1. Use semantic versioning consistently
  2. Always use annotated tags for releases
  3. Tag on main branch only (stable code)
  4. Write descriptive release notes
  5. Include breaking changes prominently
  6. Test before tagging (build, tests, linting)
  7. Use conventional commits for automation
  8. Automate versioning when possible
  9. Keep CHANGELOG.md updated
  10. Sign tags for security (git tag -s)

Key Takeaways

  • Tags mark specific points in history
  • Releases are GitHub's way to package tags
  • Semantic versioning communicates what changed
  • Annotated tags include metadata
  • Conventional commits enable automation
  • Release notes help users understand changes
  • Pre-releases let users test before stable release