Git Tags Explained
A practical guide to Git tags, including lightweight and annotated tags, versioning, release workflows, remote tags, common commands, and best practices.
Git tags are named references that point to specific Git objects, usually commits. They are commonly used to mark important points in a repository's history, such as software releases, stable versions, milestones, or deployment states.
Unlike branches, tags are normally intended to identify a fixed point in history rather than represent an ongoing line of development. A tag such as v1.0.0 can permanently identify the commit that produced version 1.0.0, making it easier to return to that exact version later.
This guide explains how Git tags work, the difference between lightweight and annotated tags, how to create and manage tags, how tags interact with remote repositories, and how they fit into release and versioning workflows.
What Is a Git Tag?
A Git tag is a reference with a human-readable name that identifies a particular object in a Git repository. In most development workflows, that object is a commit.
v1.0.0
v1.1.0
v2.0.0
release-2026-09When a tag points to a commit, you can use the tag name instead of remembering the commit hash. This is especially useful for releases because version numbers are easier for humans to understand than hashes.
git show v1.0.0The command above lets you inspect the commit and related information associated with the tag.
Git Tags vs Git Branches
Tags and branches are both Git references, but they serve different purposes. A branch normally moves forward as new commits are added. A release tag is usually intended to remain associated with the same point in history.
| Feature | Branch | Tag |
|---|---|---|
| Primary purpose | Track ongoing development | Mark a specific point in history |
| Normally moves? | Yes | No |
| Typical use | Features, fixes, development | Releases, versions, milestones |
| Example | main | v1.4.0 |
For example, main may continue receiving commits after version 1.4.0 is released, while the v1.4.0 tag continues to identify the original release commit.
Why Use Git Tags?
Tags provide stable names for important points in repository history. They are particularly useful in software projects where releases need to be reproducible and easy to identify.
- Mark production releases.
- Identify specific application or package versions.
- Create stable references for deployment systems.
- Make it easy to inspect the source code for an older release.
- Connect Git history with release notes and changelogs.
- Identify milestones in long-running projects.
- Provide stable references for documentation or external integrations.
Lightweight Git Tags
A lightweight tag is a simple named reference to an object. It does not create a separate tag object containing metadata such as a tagger, message, or signature.
git tag v1.0.0If no commit is specified, Git creates the tag for the commit currently checked out. A specific commit can also be tagged by providing its reference.
git tag v1.0.0 abc1234Lightweight tags are useful for simple local markers and situations where additional tag metadata is unnecessary.
Annotated Git Tags
An annotated tag is stored as a separate Git object and contains additional metadata. It can include the tag name, tagger information, creation date, message, and optionally a cryptographic signature.
git tag -a v1.0.0 -m "Release version 1.0.0"Annotated tags are commonly used for releases because they provide more information about why the tag exists and who created it.
| Characteristic | Lightweight tag | Annotated tag |
|---|---|---|
| Separate tag object | No | Yes |
| Message | No | Yes |
| Tagger metadata | No separate tag metadata | Yes |
| Can be signed | No | Yes |
| Typical release use | Possible | Common |
Which Type of Tag Should You Use?
For temporary local markers, lightweight tags may be sufficient. For published software releases, annotated tags are often more appropriate because they can carry release metadata and can be signed.
The most important point is to follow the project's convention. If a repository already uses annotated tags for releases, new releases should normally follow the same approach.
Creating a Git Tag
The simplest way to create a tag is to run git tag with the desired name.
git tag v1.0.0For an annotated tag, use the -a option and provide a message.
git tag -a v1.0.0 -m "Release version 1.0.0"By default, the tag points to the currently checked-out commit. If you need to tag another commit, provide its hash or another valid Git reference.
git tag -a v1.0.0 abc1234 -m "Release version 1.0.0"Creating a Tag for the Latest Commit
When the correct release commit is checked out, you can create a tag without specifying a commit.
git tag -a v2.0.0 -m "Release version 2.0.0"Before doing this in a release workflow, verify that the working tree and current commit are actually the intended release state.
Tagging a Specific Commit
Git allows you to tag any reachable commit. This is useful when the release commit is known but is not currently checked out.
git log --oneline
git tag -a v1.2.0 abc1234 -m "Release version 1.2.0"The reference can be a full commit hash, an abbreviated hash, a branch reference, or another Git expression that resolves to the intended commit.
Listing Git Tags
To see the tags available in a local repository, use git tag.
git tagYou can also filter tags using a pattern.
git tag -l "v1.*"
git tag -l "release-*"Patterns are useful when a repository contains many releases and you want to inspect only a particular version family or naming scheme.
Sorting Git Tags by Version
When tags use semantic versioning, version-aware sorting can make the list easier to read.
git tag --sort=-version:refnameThis can be useful for repositories with tags such as v1.8.0, v1.10.0, and v2.0.0, where simple alphabetical sorting does not always produce the desired version order.
Inspecting a Git Tag
The git show command can be used to inspect what a tag points to and, for annotated tags, view the tag metadata and message.
git show v1.0.0For a compact reference to the commit associated with a tag, rev-parse can be useful.
git rev-parse v1.0.0This resolves the tag reference to the corresponding object identifier. For annotated tags, additional commands can be useful when you need to distinguish the tag object from the commit it ultimately references.
Pushing a Git Tag to a Remote
Creating a tag locally does not automatically publish it to a remote repository. You need to push the tag explicitly unless your workflow or tooling handles this automatically.
git push origin v1.0.0To push multiple tags, you can specify several tag names.
git push origin v1.0.0 v1.1.0Git also provides an option for pushing all local tags.
git push origin --tagsFetching Tags from a Remote
Tags can also be retrieved from a remote repository. A fetch operation can bring remote tag information into the local repository.
git fetch originIf you want to fetch tags explicitly, Git provides tag-related options for fetch.
git fetch origin --tagsAfter fetching, the tags can be listed with git tag.
Deleting a Local Git Tag
A local tag can be removed with git tag -d.
git tag -d v1.0.0Deleting the local tag does not automatically remove a tag from a remote repository.
Deleting a Remote Git Tag
To remove a tag from a remote repository, push a deletion request to the remote.
git push origin --delete v1.0.0The same operation can be written using the refspec syntax.
git push origin :refs/tags/v1.0.0Checking Out a Git Tag
You can check out a tag to inspect the repository exactly as it existed at that point.
git checkout v1.0.0Modern Git also supports switching directly to a tag with git switch, although checking out a tag leaves you detached from a branch.
git switch --detach v1.0.0What Is Detached HEAD?
When you check out a tag, HEAD normally points directly to the tagged commit instead of a branch. Git calls this a detached HEAD state.
git statusDetached HEAD is not a problem when you are inspecting, testing, or building an old version. However, if you create commits there and then move away without creating a branch, those commits may become difficult to find.
If you need to continue development from a tagged version, create a branch instead.
git switch -c hotfix-from-v1.0.0 v1.0.0Git Tags and Semantic Versioning
Git tags are frequently combined with Semantic Versioning, commonly written as MAJOR.MINOR.PATCH. A project might use tags such as v1.0.0, v1.1.0, and v2.0.0 to identify releases.
v1.0.0
v1.1.0
v1.2.0
v2.0.0The Git tag itself does not determine whether a version follows Semantic Versioning. The project chooses the naming convention. However, using a consistent version format makes releases easier to understand and automate.
Should Git Tags Start with v?
Both v1.0.0 and 1.0.0 are valid tag names. Many projects use the v prefix because it clearly distinguishes a version tag from other references.
| Style | Example | Comment |
|---|---|---|
| With prefix | v1.4.0 | Common and easy to recognize as a version tag |
| Without prefix | 1.4.0 | Also valid and used by many projects |
| Custom release name | release-2026-09 | Useful for non-SemVer milestones |
There is no universal requirement to use the v prefix. What matters is choosing a convention and using it consistently.
Pre-release Git Tags
Projects may use version tags for pre-release versions as well. Semantic Versioning supports identifiers such as alpha, beta, and rc.
v2.0.0-alpha.1
v2.0.0-beta.1
v2.0.0-rc.1
v2.0.0These tags can identify testing or release-candidate versions without confusing them with the final stable release.
Git Tags in Release Workflows
A common release workflow uses a tag to identify the exact commit that is being released. After the feature work and fixes are merged, the project determines the next version, creates a tag, and pushes it to the remote repository.
- Review the changes included in the release.
- Run the project's tests and validation checks.
- Determine the next version according to the project's versioning rules.
- Create an annotated release tag.
- Push the tag to the remote repository.
- Generate or publish release notes.
- Deploy or publish the tagged version.
git tag -a v1.5.0 -m "Release version 1.5.0"
git push origin v1.5.0The exact order can vary. Some teams create release notes before tagging, while automated systems may create releases immediately after detecting a pushed tag.
Git Tags and CI/CD
Continuous integration and deployment systems can use tags as release triggers. For example, a CI/CD pipeline may run a production deployment whenever a tag matching a version pattern is pushed.
v1.8.0
v1.9.0
v2.0.0This approach provides a clear connection between source control and deployment. Instead of deploying an arbitrary branch state, the deployment system can be configured to build the exact commit identified by the release tag.
Git Tags and GitHub Releases
Git hosting platforms can build release interfaces around Git tags. A release can reference a tag and provide additional information such as release notes, binaries, or other artifacts.
The tag and the hosting platform's release record are related but are not exactly the same thing. The Git tag is part of the repository's Git references, while a platform release can add metadata and distribution features around that tag.
Git Tags and Changelogs
Tags provide useful boundaries for changelog generation. For example, release tooling can compare the commits between v1.4.0 and v1.5.0 and use those changes to help construct release notes.
git log v1.4.0..v1.5.0 --onelineWhen commit messages follow a consistent convention, automated tools can classify changes as features, fixes, documentation updates, performance improvements, or breaking changes.
Comparing Git Tags
Two tags can be compared to determine which commits were added between releases.
git log v1.0.0..v1.1.0 --onelineYou can also compare the actual source changes between two tagged versions.
git diff v1.0.0 v1.1.0This is useful when investigating what changed between releases or verifying that a release contains the expected modifications.
Finding the Tag That Contains a Commit
Git can show which tags point to or contain a particular commit. One useful command is git tag with the --contains option.
git tag --contains abc1234This can help determine which releases include a particular change, especially when investigating bugs or verifying whether a fix has reached a released version.
Moving or Replacing a Git Tag
A tag can technically be moved to another commit, but doing so after publishing it is usually undesirable. Developers and automation may already have the original reference.
git tag -f v1.0.0 <commit>If the tag has already been pushed, updating the remote requires a forced push.
git push origin --force v1.0.0Signed Git Tags
Annotated tags can be cryptographically signed. Signed tags provide a way to verify that the tag was created by the expected signing identity and that the signed tag object has not been altered.
git tag -s v1.0.0 -m "Release version 1.0.0"Signing is most useful when a project has a defined trust and key-management process. It should be treated as part of a broader release security workflow rather than as a replacement for access controls.
Tag Naming Best Practices
A consistent naming scheme makes tags easier to discover, sort, automate, and understand.
- Choose one version naming convention and use it consistently.
- Use Semantic Versioning when it matches the project's release model.
- Decide whether version tags use a v prefix.
- Use annotated tags for important releases when metadata is useful.
- Avoid changing published release tags.
- Keep release tags associated with reproducible source states.
- Document tag naming rules in the project's contribution or release documentation.
- Protect tags that trigger automated deployments.
Common Git Tag Mistakes
| Mistake | Why it causes problems | Better approach |
|---|---|---|
| Creating a tag on the wrong commit | The tag no longer represents the intended release | Verify the commit before creating the tag |
| Forgetting to push the tag | The release exists only locally | Push the intended tag explicitly |
| Using inconsistent names | Searching and automation become harder | Document and follow one naming convention |
| Moving a published tag | Existing references may point to different source code | Treat published tags as stable |
| Deleting release tags casually | Builds and external references may break | Avoid deleting published tags without a clear reason |
| Using --tags without checking local tags | Unintended tags may be published | Push specific tags when possible |
| Creating commits from a tag without a branch | Commits may be created in detached HEAD | Create a branch when continuing development |
A Practical Git Tag Release Workflow
A simple release process can combine Git tags, semantic versions, consistent commit messages, and automated release notes.
git status
git log --oneline -10
git tag --sort=-version:refname
git tag -a v1.5.0 -m "Release version 1.5.0"
git show v1.5.0
git push origin v1.5.0The exact commands depend on the project, but the important principle is to verify the release state before creating and publishing the tag.
Git Tags in Monorepos
Monorepos can require more detailed tagging strategies because a single repository may contain several applications or packages. A project might tag the entire repository for a coordinated release or use package-specific tag naming conventions.
web-v2.1.0
api-v2.1.0
shared-v1.8.0The correct approach depends on how the repository builds and releases its individual packages. The naming scheme should make it clear which component a tag belongs to.
Git Tags for Hotfixes
Tags are also useful for documenting hotfix releases. For example, if version 2.1.0 contains a production bug and the project releases a patch, the next version might be tagged v2.1.1.
v2.1.0
v2.1.1The patch tag gives the team a stable reference for the exact source code that contains the fix.
Useful Git Tag Commands
| Command | Purpose |
|---|---|
| git tag | List local tags |
| git tag v1.0.0 | Create a lightweight tag |
| git tag -a v1.0.0 -m "Release version 1.0.0" | Create an annotated tag |
| git show v1.0.0 | Inspect a tag |
| git tag -d v1.0.0 | Delete a local tag |
| git push origin v1.0.0 | Push one tag |
| git push origin --tags | Push all local tags not on the remote |
| git push origin --delete v1.0.0 | Delete a remote tag |
| git fetch origin --tags | Fetch tags from a remote |
| git tag --contains <commit> | Find tags containing a commit |
| git diff v1.0.0 v1.1.0 | Compare two tagged versions |
Git Tags and Commit Messages
Tags identify important points in history, while commit messages explain the individual changes that led to those points. Together, they provide a useful release history.
For example, a release tag such as v2.0.0 can identify the final release commit, while the commits between v1.5.0 and v2.0.0 explain the features, fixes, refactors, and breaking changes introduced during development.
This becomes especially powerful when commit messages follow a predictable convention. Release tooling can use the tagged boundaries and structured commit history to produce more useful release notes.
Git Tags and Reproducible Releases
A tag provides a stable reference to source code, but a completely reproducible build can depend on more than the Git commit alone. Dependency versions, build configuration, generated files, external services, and the build environment can also affect the resulting artifact.
For this reason, tags should be considered one important part of release reproducibility rather than the entire solution. Projects that require highly reproducible builds should also manage dependencies and build environments carefully.
Helpful Git Release Tools
Versioning and release workflows can be supported by several categories of developer tools. A semantic version calculator can help determine the next version from a release type. Release notes and changelog generators can turn structured project history into release documentation.
Git commit generators and Conventional Commit generators can help create consistent commit messages, which in turn makes automated release workflows easier to maintain.
What is a Git tag?
A Git tag is a named reference to a Git object, most commonly a commit. Tags are frequently used to mark releases, versions, milestones, and other important points in repository history.
What is the difference between a Git tag and a branch?
A branch normally moves as new commits are added, while a tag is generally used to identify a fixed point in repository history. For example, main can continue to change after v1.0.0 has been created.
What is the difference between lightweight and annotated tags?
A lightweight tag is a simple reference, while an annotated tag is a separate Git object containing metadata such as a tagger, date, message, and optional signature. Annotated tags are commonly used for releases.
How do I push a Git tag to GitHub or another remote?
Create the tag locally and push it explicitly with a command such as git push origin v1.0.0. You can also push multiple tags or use --tags when you intentionally want to publish all relevant local tags.
Can I delete a Git tag?
Yes. git tag -d removes a local tag, while git push origin --delete <tag> removes a tag from a remote. Published release tags should generally not be deleted without a clear reason because other systems may depend on them.
Should Git tags use semantic versioning?
They do not have to, but Semantic Versioning is a common choice for software releases because it provides a predictable MAJOR.MINOR.PATCH format. The project should choose and consistently document its versioning convention.
Can a Git tag be moved to another commit?
Yes, Git technically allows tags to be replaced or force-pushed to another commit. However, moving a published release tag can make historical references and automated builds inconsistent, so published tags are usually treated as immutable.
Conclusion
Git tags provide stable, human-readable references to important points in a repository's history. They are especially useful for software releases because a version such as v1.5.0 is easier to identify and reuse than a raw commit hash.
For important releases, annotated tags provide useful metadata and can also be signed. A consistent naming convention, careful release verification, and explicit tag publishing help keep release history predictable.
When Git tags are combined with semantic versioning, structured commit messages, changelogs, release notes, and CI/CD automation, they become an important part of a reliable software release workflow.