Tags & Releases

What's a tag?

A tag is a permanent name pinned to a specific commit — almost always a version number like v1.0.0. Unlike a branch, a tag doesn't move; it always points at the same commit, so anyone can come back to "exactly what we shipped as 1.0".

Lightweight vs annotated

  • Lightweight — just a name on a commit. Fine for a quick private bookmark.
  • Annotated — stores a message, your name and the date. This is the right choice for real releases, and what most tools expect.

Create a tag

Terminal
$ git tag v1.0.0                        # lightweight
$ git tag -a v1.0.0 -m "First stable release"  # annotated (recommended)
In VS Code
  1. Command Palette → Git: Create Tag
  2. Type the tag name and an optional message

Tag the commit you’re on — or tag an older one by adding its hash: git tag -a v0.9.0 a1b2c3d -m "Beta".

List and inspect tags

See your tags

Terminal
$ git tag                 # list all
$ git tag -l "v1.*"        # filter
$ git show v1.0.0          # what the tag points to + its message
In VS Code
  1. The Git Graph extension shows tags as labels on the commit graph

Push tags to GitHub

Here's the gotcha that trips everyone up: tags don't get pushed by git push. You push them explicitly.

Send tags to the remote

Terminal
$ git push origin v1.0.0     # push one tag
$ git push origin --tags     # push all your tags
In VS Code
  1. Command Palette → Git: Push (Follow Tags), or use the '…' menu → Push Tags

If a teammate's tag is missing locally, git fetch --tags pulls them down.

Deleting a tag

Remove a tag locally and on GitHub

Terminal
$ git tag -d v1.0.0                    # delete locally
$ git push origin --delete v1.0.0      # delete on GitHub
In VS Code
  1. Command Palette → Git: Delete Tag for the local copy

Semantic versioning — what the numbers mean

Most projects number releases as MAJOR.MINOR.PATCH (e.g. 2.4.1):

  • MAJOR — breaking changes that aren't backward-compatible.
  • MINOR — new features that still work with old code.
  • PATCH — bug fixes only.

So 1.4.0 → 1.4.1 is a bug fix, 1.4.1 → 1.5.0 adds a feature, and 1.5.0 → 2.0.0 breaks something on purpose.

From tag to GitHub Release

A GitHub Release dresses up a tag with a title, written notes ("what's new"), and optional downloadable files. It's the page users actually visit to grab a version. You can make one from the website (Releases → Draft a new release → pick the tag) or from the command line with the GitHub CLI.

Publish a release with the GitHub CLI

Terminal
$ git push origin v1.0.0
$ gh release create v1.0.0 --title "v1.0.0" --notes "First stable release 🎉"
In VS Code
  1. On github.com: the repo's Releases section → Draft a new release
  2. Choose your tag, add a title and notes, then Publish release
  3. GitHub can auto-generate notes from your merged pull requests

gh is the GitHub CLI (cli.github.com). 'Generate release notes' turns your merged PRs into a changelog automatically.

Up next: the Fix-it chapters — when something looks wrong, find your exact error and fix it, starting with the gentlest undos.

FAQ

Frequently Asked Questions

What is the difference between a tag and a branch?
A branch moves forward as you commit. A tag is a fixed label pinned to one commit — used to mark a version like v1.0.0, so you can always return to exactly what you shipped.
Why didn’t my tag push to GitHub?
Because git push doesn't send tags. Push them explicitly with git push origin <tag>, or push them all with git push origin --tags.
Lightweight or annotated tag — which should I use?
Use an annotated tag for releases (git tag -a v1.0.0 -m "…"); it stores a message, author and date. Lightweight tags are just a bare pointer, fine for quick private bookmarks.
What is semantic versioning?
A MAJOR.MINOR.PATCH numbering scheme: bump PATCH for bug fixes, MINOR for backward-compatible features, and MAJOR for breaking changes — e.g. 1.4.2 → 2.0.0.