Skip to content

Git Tags, Releases & Semantic Versioning Guide

DodaTech Updated 2026-06-22 5 min read

In this tutorial, you'll learn about Git Tags, Releases & Semantic Versioning Guide. We cover key concepts, practical examples, and best practices.

A Git tag is a reference that points to a specific commit to mark version numbers, and unlike branches, tags do not move when new commits are added.

In this tutorial, you'll learn Git tags and how they integrate with release management and semantic versioning. Tags mark specific points in history as important — typically releases. By the end, you'll create annotated and signed tags, manage releases on GitHub and GitLab, and automate version bumps with CI/CD.

flowchart LR
  A[Commit 1] --> B[Commit 2]
  B --> C[Commit 3]
  C --> D[Commit 4]
  C --> E{v1.0.0 Tag}
  D --> F[Commit 5]
  F --> G{v1.1.0 Tag}
  E -.-> H[Release v1.0.0]
  G -.-> I[Release v1.1.0]

Semantic Versioning (SemVer)

SemVer uses the format MAJOR.MINOR.PATCH:

Component When to Bump Example
MAJOR Incompatible API changes 1.0.0 to 2.0.0
MINOR Backward-compatible new features 1.0.0 to 1.1.0
PATCH Backward-compatible bug fixes 1.0.0 to 1.0.1

Pre-release tags: 1.0.0-alpha.1, 1.0.0-beta.2, 1.0.0-rc.1

Creating Tags

Lightweight Tags

A lightweight tag is just a pointer to a commit:

git tag v1.0.0
git tag v1.0.0 a1b2c3d  # Tag a specific commit

Annotated Tags

An annotated tag stores the tagger name, email, date, and a message:

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

Expected output:

$ git tag -a v1.0.0 -m "Release version 1.0.0"
$ git show v1.0.0
tag v1.0.0
Tagger: Your Name <you@example.com>
Date:   Mon Jun 22 10:00:00 2026 +0000

Release version 1.0.0

commit a1b2c3d...

Pushing Tags

Tags are not automatically pushed with commits:

git push origin v1.0.0        # Push one tag
git push origin --tags        # Push all tags

Signed Tags

Sign tags with GPG for verification:

git tag -s v1.0.0 -m "Release 1.0.0"

Verify a signed tag:

git tag -v v1.0.0

Expected output:

object a1b2c3d...
type commit
tag v1.0.0
tagger Your Name <you@example.com> ...
gpg: Signature made Mon Jun 22 10:00:00 2026
gpg: Good signature from "Your Name <you@example.com>"

Deleting Tags

git tag -d v1.0.0              # Delete local tag
git push origin --delete v1.0.0  # Delete remote tag

Releases on GitHub

Create a release from a tag using the GitHub CLI:

gh release create v1.0.0 --title "v1.0.0" --notes "Initial release"

Automated Versioning with CI/CD

Use CI/CD to auto-tag releases:

# .github/workflows/release.yml
name: Create Release
on:
  push:
    branches: [main]
jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Bump version
        id: bump
        run: |
          git tag -a v1.0.${{ github.run_number }} -m "Release"
          git push origin v1.0.${{ github.run_number }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Comparison: Tag Types

Feature Lightweight Annotated Signed
Storage Just a ref Full object Full object + signature
Metadata None Name, email, date, message Same + GPG signature
Use case Temporary markers Official releases Verified releases
Command git tag v1.0 git tag -a v1.0 -m "msg" git tag -s v1.0 -m "msg"

Common Errors

Error Cause Fix
fatal: tag 'v1.0' already exists Tag already created locally Delete and recreate or use a new tag
Everything up-to-date on tag push Tag not pushed Use git push origin <tagname>
gpg: signing failed Missing GPG key Generate and configure GPG key
No tag exactly matches Wrong tag name Check with git tag -l
Tag not found on fetch Remote tags not fetched git fetch --tags
detached HEAD on checkout Checked out a tag Create a branch: git switch -c branch-name
Cannot delete tag Tag is release protected Delete GitHub release first

Practice Questions

What is the difference between a lightweight and an annotated tag?

A lightweight tag is just a pointer to a commit (a ref). An annotated tag is a full Git object stored in the object database — it includes the tagger's name, email, date, a message, and can be signed with GPG. Always use annotated tags for releases.

How do I tag a previous commit?

Find the commit hash with git log, then run git tag -a v1.0.0 <commit-hash> -m "Release notes". The tag will point to that historical commit.

Do tags get pushed automatically?

No. By default, git push does not send tags. You must explicitly push tags with git push origin <tagname> or git push origin --tags. Some developers prefer pushing tags individually to avoid pushing unwanted tags.

What is the MAJOR.MINOR.PATCH format?

MAJOR version bumps for breaking API changes. MINOR version bumps for backward-compatible new features. PATCH version bumps for backward-compatible bug fixes. This is the semantic versioning (SemVer) standard.

How do I create a GitHub release from a tag?

Use the GitHub web UI: Repo > Releases > Create a new release. Select the tag, add release notes, attach binaries, and publish. Or use the CLI: gh release create v1.0.0 --title "v1.0.0" --notes "Release notes"

Challenge

Create a repository with five commits. Tag the third commit as v0.1.0 (annotated). Make two more commits, then tag the latest as v0.2.0-beta (lightweight). Push both tags. Create a release on GitHub for v0.1.0 with release notes describing the features. Delete the v0.2.0-beta tag locally and remotely.

Real-World Task

Implement an automated release workflow using GitLab CI/CD that creates a tag and release when code is merged to main. The pipeline should: bump the version based on commit messages (using semantic-release or a custom script), create an annotated and signed tag, generate release notes from commit history, and push the tag. This automated release process is used at DodaTech for DodaZIP to ensure every version is traceable and signed.


Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro