What “Releases” and “Snapshots” Mean in Git
A Git tag is a human-friendly name attached to a specific commit. Unlike a branch, a tag does not move when you add new commits. That makes tags ideal for marking stable milestones such as “v1.0.0” or “2026-01-15-demo”.
In small projects, tags act like recoverable checkpoints: you can quickly compare versions, share an exact state with someone else, or roll back to a known-good point when something breaks.
Lightweight vs Annotated Tags
Lightweight tags (quick pointers)
A lightweight tag is just a name pointing at a commit. It’s fast to create and useful for personal or temporary markers.
git tag v1.0.0Annotated tags (recommended for releases)
An annotated tag is a full Git object that includes a message, author, and date (and can be signed). For anything you consider a “release” or share with others, annotated tags are a better habit because they capture context.
git tag -a v1.0.0 -m "Release v1.0.0: first stable CLI"Practical rule of thumb: use annotated tags for releases; use lightweight tags only for quick local markers you don’t care to document.
Continue in our app.
You can listen to the audiobook with the screen off, receive a free certificate for this course, and also have access to 5,000 other free online courses.
Or continue reading below...Download the app
Naming Conventions: v1.0.0 and Friends
Consistent naming makes tags easy to scan, sort, and compare. A common convention is semantic versioning: vMAJOR.MINOR.PATCH.
- MAJOR: breaking changes (users must adapt)
- MINOR: new features, backward compatible
- PATCH: bug fixes only
Examples:
v1.0.0initial stable releasev1.0.1bug fix releasev1.1.0adds features without breaking existing usage
Keep tag names simple: avoid spaces; prefer dots and hyphens. If you need pre-releases, you can add suffixes like v1.2.0-rc.1.
Tagging a Specific Commit
By default, git tag tags the current commit (the one HEAD points to). You can also tag an older commit by providing its hash.
Tag the current commit
git tag -a v1.0.0 -m "Release v1.0.0: stable after tests"Tag an earlier commit
git log --oneline --decorateCopy the commit hash you want, then:
git tag -a v0.9.0 1a2b3c4 -m "v0.9.0: last beta"If you accidentally tagged the wrong commit, you can delete and recreate the tag (locally) by removing it and tagging again.
git tag -d v1.0.0git tag -a v1.0.0 <correct-commit> -m "Release v1.0.0: stable"Listing and Inspecting Tags
List tags
git tagTo filter by pattern:
git tag -l "v1.*"Show what a tag points to
To see the tagged commit and (for annotated tags) the tag message:
git show v1.0.0To see the commit hash a tag resolves to:
git rev-parse v1.0.0Pushing Tags to a Remote
Tags are not automatically pushed when you push commits. You must push them explicitly, which is a helpful safety feature: you can create tags locally, verify them, then publish.
Push one tag
git push origin v1.0.0Push all tags
git push origin --tagsIn small projects, prefer pushing individual release tags so you don’t accidentally publish experimental tags.
Practical Release Habits for Small Projects
1) Tag only after a passing build/test
Make “green build first” your default. The tag should represent a state you can confidently return to.
- Run your test command (whatever your project uses).
- Ensure the working tree is clean.
- Create an annotated tag with a meaningful message.
git status# run your tests heregit tag -a v1.0.0 -m "Release v1.0.0: tests passing; adds config loader"2) Write tag messages that capture notable changes
A good tag message is short but specific. Include what changed and why it matters.
- Good: “v1.1.0: adds JSON export; fixes crash on empty input”
- Too vague: “release”
3) Use tags to compare versions
Tags are excellent anchors for diffs.
git diff v1.0.0 v1.1.0You can also focus on file-level changes:
git diff v1.0.0 v1.1.0 -- path/to/file.py4) Return to a known-good state (detached HEAD)
Checking out a tag puts you in a detached HEAD state: you’re viewing the project exactly as it was at that tag, but you’re not on a branch that will advance.
git checkout v1.0.0In detached HEAD, you can build, run, or inspect safely. If you need to make a fix starting from that release, create a branch immediately so your work is anchored.
Create a hotfix branch from a tag
git checkout -b hotfix/v1.0.1 v1.0.0Now you can commit your fix on hotfix/v1.0.1, test, and then tag a patch release when ready.
# edit files, run testsgit commit -am "Fix: handle empty config file"git tag -a v1.0.1 -m "Release v1.0.1: fix empty config handling"Mini-Release Exercise: Two Tags and a Changelog
This exercise simulates a small project release cycle: tag a stable version, make a change, tag again, then generate a concise changelog between the two tags.
Step 1: Ensure you are at a stable point
git statusMake sure your working tree is clean and tests/build pass.
Step 2: Create the first release tag (annotated)
git tag -a v1.0.0 -m "Release v1.0.0: stable baseline"Step 3: Make a small change and commit it
# edit one file (e.g., add a small feature or fix)git commit -am "Add: show version in --help output"Step 4: Tag the next release
Again, do this after verifying the project still works.
git tag -a v1.1.0 -m "Release v1.1.0: adds version in help"Step 5: Compare versions with a diff
git diff v1.0.0 v1.1.0Step 6: Produce a concise changelog from git log
Generate a one-line-per-commit changelog between the tags:
git log --oneline v1.0.0..v1.1.0If you want a slightly richer changelog including dates and authors:
git log --pretty=format:"- %s (%an, %ad)" --date=short v1.0.0..v1.1.0Optional: Push the release tags
git push origin v1.0.0git push origin v1.1.0