Learn to create Git tags for releases, understand semantic versioning, and manage software releases professionally.
Tags are references that point to specific commits in Git history. Unlike branches, tags don't move - they're like bookmarks that mark important points like releases.
Professional software development requires a systematic approach to versioning. Semantic versioning (SemVer) provides a clear way to communicate what changes are in each release. Combined with Git tags and GitHub releases, you can build a robust release management system.
In this lesson, you'll learn how to tag releases, follow versioning best practices, and create professional releases.
Tags are permanent references to specific commits, typically used to mark release points.
Why Use Tags?
Two Types of Tags:
1. Lightweight Tags
Simple pointers to commits (like a branch that doesn't move):
1# Create lightweight tag
2git tag v1.0.0
3
4# Tag specific commit
5git tag v1.0.0 abc12342. Annotated Tags (Recommended)
Full objects with metadata:
1# Create annotated tag
2git tag -a v1.0.0 -m "Release version 1.0.0"
3
4# Tag specific commit
5git tag -a v1.0.0 abc1234 -m "Release version 1.0.0"Annotated Tag Contains:
Comparison:
| Feature | Lightweight | Annotated |
|---------|------------|-----------|
| Metadata | No | Yes |
| Message | No | Yes |
| Tagger info | No | Yes |
| GPG signing | No | Yes |
| Recommended for | Temporary | Releases |
1# View tag details
2git show v1.0.0
3
4# Annotated tag shows:
5# tag v1.0.0
6# Tagger: Your Name <email>
7# Date: Mon Nov 25 10:00:00 2024
8#
9# Release version 1.0.0
10#
11# commit abc1234...Essential commands for managing tags in your repository.
Creating Tags:
1# Annotated tag (recommended)
2git tag -a v1.0.0 -m "Initial stable release"
3
4# Annotated tag with longer message
5git tag -a v1.0.0
6
7# Opens editor for message:
8# Release v1.0.0
9#
10# Features:
11# - User authentication
12# - Dashboard
13# - API endpoints
14
15# Lightweight tag
16git tag v1.0.0-beta
17
18# Tag older commit
19git tag -a v0.9.0 abc1234 -m "Beta release"Listing Tags:
1# List all tags
2git tag
3
4# List with pattern
5git tag -l "v1.*"
6
7# List with details
8git tag -n
9# v1.0.0 Initial stable release
10# v1.1.0 Add user profiles
11
12# Sort by version
13git tag --sort=-version:refnameViewing Tags:
1# Show tag and commit info
2git show v1.0.0
3
4# Show just commit
5git show v1.0.0 --quiet
6
7# See what's different between tags
8git diff v1.0.0 v1.1.0
9
10# Log between tags
11git log v1.0.0..v1.1.0 --onelinePushing Tags:
1# Push specific tag
2git push origin v1.0.0
3
4# Push all tags
5git push origin --tags
6
7# Push all annotated tags (Git 2.4+)
8git push --follow-tagsDeleting Tags:
1# Delete local tag
2git tag -d v1.0.0
3
4# Delete remote tag
5git push origin --delete v1.0.0
6# or
7git push origin :refs/tags/v1.0.0Checking Out Tags:
1# Checkout tag (detached HEAD)
2git checkout v1.0.0
3
4# Create branch from tag
5git checkout -b hotfix-v1.0.1 v1.0.0
6# or
7git switch -c hotfix-v1.0.1 v1.0.0Semantic Versioning is a versioning scheme that conveys meaning about the underlying changes.
Format: MAJOR.MINOR.PATCH
1v1.2.3
2│ │ └── PATCH: Bug fixes, no API changes
3│ └──── MINOR: New features, backwards compatible
4└────── MAJOR: Breaking changesWhen to Increment:
| Version | When to Increment | Example |
|---------|-------------------|---------|
| MAJOR | Breaking API changes | 1.x.x → 2.0.0 |
| MINOR | New backwards-compatible features | x.1.x → x.2.0 |
| PATCH | Bug fixes | x.x.1 → x.x.2 |
Examples:
1# Bug fix only
2v1.2.3 → v1.2.4
3
4# New feature, backwards compatible
5v1.2.4 → v1.3.0 # Reset patch to 0
6
7# Breaking change
8v1.3.0 → v2.0.0 # Reset minor and patch to 0Pre-release Versions:
1# Alpha (early development)
2v2.0.0-alpha.1
3v2.0.0-alpha.2
4
5# Beta (feature complete, testing)
6v2.0.0-beta.1
7
8# Release candidate (almost ready)
9v2.0.0-rc.1
10v2.0.0-rc.2
11
12# Final release
13v2.0.0Build Metadata:
1# Include build info (ignored for precedence)
2v1.2.3+build.123
3v1.2.3+20241125Version Precedence:
1# Lower to higher
21.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-beta < 1.0.0-rc.1 < 1.0.0
3
4# Examples
50.9.0 < 1.0.0-alpha < 1.0.0 < 1.0.1 < 1.1.0 < 2.0.0Common Patterns:
1# Initial development
20.1.0, 0.2.0, 0.3.0 # API may change anytime
3
4# First stable release
51.0.0
6
7# Typical progression
81.0.0 → 1.0.1 → 1.1.0 → 1.1.1 → 1.2.0 → 2.0.0GitHub Releases build on Git tags to provide downloadable packages and release notes.
Via GitHub Web Interface:
Via GitHub CLI:
1# Create release from existing tag
2gh release create v1.0.0 --title "Version 1.0.0" --notes "Release notes here"
3
4# Create release with files
5gh release create v1.0.0 ./dist/app.zip --title "v1.0.0"
6
7# Create draft release
8gh release create v1.0.0 --draft
9
10# Create pre-release
11gh release create v1.0.0-beta.1 --prerelease
12
13# Generate notes automatically
14gh release create v1.0.0 --generate-notes
15
16# Create from release notes file
17gh release create v1.0.0 -F CHANGELOG.mdRelease Notes Template:
1## What's New
2
3### Features
4- Add user authentication (#123)
5- Implement dashboard analytics (#145)
6
7### Bug Fixes
8- Fix login redirect issue (#156)
9- Resolve memory leak in API client (#162)
10
11### Breaking Changes
12- Remove deprecated `getUserData` method
13- Change authentication token format
14
15### Dependencies
16- Upgrade React to 18.2.0
17- Update security dependencies
18
19## Upgrade Guide
20To upgrade from v0.x:
211. Update configuration file format
222. Run migration script: `npm run migrate`
23
24## Contributors
25@username1, @username2Listing Releases:
1# List releases
2gh release list
3
4# View specific release
5gh release view v1.0.0
6
7# Download release assets
8gh release download v1.0.0A systematic approach to creating releases in your projects.
Pre-Release Checklist:
1- [ ] All tests passing
2- [ ] Documentation updated
3- [ ] CHANGELOG.md updated
4- [ ] Version bumped in package.json/similar
5- [ ] Code reviewed and approved
6- [ ] No blocking bugs
7- [ ] Dependencies up to dateRelease Process:
1# 1. Ensure you're on main and up-to-date
2git switch main
3git pull origin main
4
5# 2. Run tests
6npm test
7npm run lint
8
9# 3. Update version (package.json, etc.)
10npm version patch # or minor, major
11# This also creates a commit and tag
12
13# 4. Or manually update and tag
14# Edit package.json version
15git add package.json
16git commit -m "Bump version to 1.2.0"
17git tag -a v1.2.0 -m "Release version 1.2.0"
18
19# 5. Push code and tags
20git push origin main
21git push origin v1.2.0
22# or
23git push origin main --tags
24
25# 6. Create GitHub release
26gh release create v1.2.0 --generate-notesHotfix Release:
1# 1. Create hotfix branch from tag
2git switch -c hotfix/v1.2.1 v1.2.0
3
4# 2. Make the fix
5git commit -m "Fix critical bug"
6
7# 3. Update version and tag
8git tag -a v1.2.1 -m "Hotfix release"
9
10# 4. Merge to main
11git switch main
12git merge hotfix/v1.2.1
13
14# 5. Push everything
15git push origin main --tags
16
17# 6. Clean up
18git branch -d hotfix/v1.2.1Automated Releases (GitHub Actions):
1# .github/workflows/release.yml
2name: Release
3
4on:
5 push:
6 tags:
7 - 'v*'
8
9jobs:
10 release:
11 runs-on: ubuntu-latest
12 steps:
13 - uses: actions/checkout@v4
14
15 - name: Build
16 run: npm run build
17
18 - name: Create Release
19 uses: actions/create-release@v1
20 env:
21 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
22 with:
23 tag_name: ${{ github.ref }}
24 release_name: Release ${{ github.ref }}
25 draft: false
26 prerelease: falseVersion in Code:
1// Include version in your app
2const version = process.env.npm_package_version;
3// or
4import { version } from '../package.json';
5
6console.log(`App version: ${version}`);Visualize semantic versioning and see how different changes affect version numbers.
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>Semantic Versioning Visualizer</title>
7 <style>
8 * { margin: 0; padding: 0; box-sizing: border-box; }
9 body {
10 font-family: 'Monaco', monospace;
11 background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
12 min-height: 100vh;
13 color: #e0e0e0;
14 padding: 20px;
15 }
16 .container { max-width: 900px; margin: 0 auto; }
17 h1 { text-align: center; color: #ffd93d; margin-bottom: 30px; }
18
19 .version-display {
20 text-align: center;
21 margin-bottom: 30px;
22 }
23 .version-number {
24 font-size: 4rem;
25 font-weight: bold;
26 letter-spacing: 5px;
27 }
28 .version-number .major { color: #ff6b6b; }
29 .version-number .minor { color: #ffd93d; }
30 .version-number .patch { color: #6bcb77; }
31 .version-number .dot { color: #888; }
32
33 .controls {
34 display: flex;
35 justify-content: center;
36 gap: 15px;
37 margin-bottom: 30px;
38 flex-wrap: wrap;
39 }
40 .btn {
41 padding: 15px 30px;
42 border: none;
43 border-radius: 10px;
44 cursor: pointer;
45 font-weight: bold;
46 font-size: 0.9rem;
47 transition: all 0.3s;
48 }
49 .btn:hover { transform: translateY(-3px); }
50 .btn-major { background: #ff6b6b; color: white; }
51 .btn-minor { background: #ffd93d; color: #1a1a2e; }
52 .btn-patch { background: #6bcb77; color: #1a1a2e; }
53 .btn-reset { background: #666; color: white; }
54
55 .explanation {
56 background: rgba(0,0,0,0.4);
57 border-radius: 15px;
58 padding: 25px;
59 margin-bottom: 25px;
60 }
61 .explanation h2 { color: #00d4aa; margin-bottom: 15px; }
62
63 .semver-grid {
64 display: grid;
65 grid-template-columns: repeat(3, 1fr);
66 gap: 15px;
67 }
68 .semver-card {
69 background: rgba(0,0,0,0.3);
70 border-radius: 10px;
71 padding: 20px;
72 text-align: center;
73 }
74 .semver-card h3 { margin-bottom: 10px; font-size: 1.1rem; }
75 .semver-card.major h3 { color: #ff6b6b; }
76 .semver-card.minor h3 { color: #ffd93d; }
77 .semver-card.patch h3 { color: #6bcb77; }
78 .semver-card p { color: #888; font-size: 0.85rem; line-height: 1.5; }
79
80 .history {
81 background: rgba(0,0,0,0.4);
82 border-radius: 15px;
83 padding: 25px;
84 }
85 .history h2 { color: #00d4aa; margin-bottom: 15px; }
86 .timeline { display: flex; flex-direction: column; gap: 10px; }
87 .version-entry {
88 display: flex; align-items: center; gap: 15px;
89 padding: 12px; background: rgba(255,255,255,0.05);
90 border-radius: 8px;
91 }
92 .version-tag {
93 padding: 5px 15px; border-radius: 5px;
94 font-weight: bold; min-width: 80px; text-align: center;
95 }
96 .version-tag.major { background: rgba(255,107,107,0.2); color: #ff6b6b; }
97 .version-tag.minor { background: rgba(255,217,61,0.2); color: #ffd93d; }
98 .version-tag.patch { background: rgba(107,203,119,0.2); color: #6bcb77; }
99 .version-desc { color: #aaa; font-size: 0.85rem; }
100
101 @media (max-width: 600px) {
102 .semver-grid { grid-template-columns: 1fr; }
103 .version-number { font-size: 2.5rem; }
104 }
105 </style>
106</head>
107<body>
108 <div class="container">
109 <h1>Semantic Versioning</h1>
110
111 <div class="version-display">
112 <div class="version-number">
113 <span class="major" id="major">1</span><span class="dot">.</span>
114 <span class="minor" id="minor">0</span><span class="dot">.</span>
115 <span class="patch" id="patch">0</span>
116 </div>
117 </div>
118
119 <div class="controls">
120 <button class="btn btn-major" onclick="bumpMajor()">Major +1</button>
121 <button class="btn btn-minor" onclick="bumpMinor()">Minor +1</button>
122 <button class="btn btn-patch" onclick="bumpPatch()">Patch +1</button>
123 <button class="btn btn-reset" onclick="resetVersion()">Reset</button>
124 </div>
125
126 <div class="explanation">
127 <h2>When to Increment</h2>
128 <div class="semver-grid">
129 <div class="semver-card major">
130 <h3>MAJOR</h3>
131 <p>Breaking changes that are NOT backwards compatible. Users must update their code.</p>
132 </div>
133 <div class="semver-card minor">
134 <h3>MINOR</h3>
135 <p>New features that ARE backwards compatible. Existing code keeps working.</p>
136 </div>
137 <div class="semver-card patch">
138 <h3>PATCH</h3>
139 <p>Bug fixes that don't change the API. No new features.</p>
140 </div>
141 </div>
142 </div>
143
144 <div class="history">
145 <h2>Version History</h2>
146 <div class="timeline" id="timeline">
147 <div class="version-entry">
148 <span class="version-tag major">v1.0.0</span>
149 <span class="version-desc">Initial stable release</span>
150 </div>
151 </div>
152 </div>
153 </div>
154
155 <script>
156 let major = 1, minor = 0, patch = 0;
157 const changes = {
158 major: ['Breaking API change', 'Remove deprecated features', 'Major architecture overhaul'],
159 minor: ['Add new feature', 'Add new endpoint', 'Deprecate old method'],
160 patch: ['Fix bug', 'Security patch', 'Performance improvement']
161 };
162
163 function updateDisplay() {
164 document.getElementById('major').textContent = major;
165 document.getElementById('minor').textContent = minor;
166 document.getElementById('patch').textContent = patch;
167 }
168
169 function addHistory(type) {
170 const msg = changes[type][Math.floor(Math.random() * changes[type].length)];
171 const entry = document.createElement('div');
172 entry.className = 'version-entry';
173 entry.innerHTML = `176`;
177 document.getElementById('timeline').prepend(entry);
178 }
179
180 function bumpMajor() {
181 major++; minor = 0; patch = 0;
182 updateDisplay();
183 addHistory('major');
184 }
185
186 function bumpMinor() {
187 minor++; patch = 0;
188 updateDisplay();
189 addHistory('minor');
190 }
191
192 function bumpPatch() {
193 patch++;
194 updateDisplay();
195 addHistory('patch');
196 }
197
198 function resetVersion() {
199 major = 1; minor = 0; patch = 0;
200 updateDisplay();
201 document.getElementById('timeline').innerHTML = `206`;
207 }
208 </script>
209</body>
210</html>This visualizer helps you understand semantic versioning:
Version Format: MAJOR.MINOR.PATCH
Click the buttons to see:
Version History:
Each bump adds to the history with a random change description that matches the version type.
Key Principles:
Excellent! You now understand how to version and release software. The next lesson covers collaboration and pull requests - the heart of team development with Git.
Your progress is saved in this browser, on this device only.