By admin , 29 April 2026

Tags as release markers

A Git tag is an immutable label on a commit. Annotated tags carry a tagger name, date, and message; lightweight tags are just a name. Use annotated tags for releases - they are first-class objects, GPG-signable, and queryable.

Creating tags

# Annotated
git tag -a v1.4.0 -m "Release 1.4.0"

# Signed (recommended for releases)
git tag -s v1.4.0 -m "Release 1.4.0"

# Lightweight (not recommended for releases)
git tag v1.4.0-alpha

Pushing tags

Tags are not pushed by default:

git push origin v1.4.0
git push --tags                # push all tags (risky on large repos)
git push --follow-tags          # push commits and reachable annotated tags

--follow-tags is the sweet spot - tags travel with their commits but unrelated tags do not.

Triggering CI on tags

GitHub Actions example that builds and publishes when a tag matches v*.*.*:

on:
  push:
    tags:
      - 'v*.*.*'

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run build
      - run: npm publish
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

GitLab and other CIs use the same pattern - filter pipelines on a tag ref.

SemVer and prereleases

Stick to Semantic Versioning. CI logic can detect prerelease tags:

if [[ "$TAG" =~ -(alpha|beta|rc) ]]; then
  npm publish --tag next
else
  npm publish
fi

Generating changelogs from tags

git log v1.3.0..v1.4.0 --oneline --no-merges
# Or with conventional-changelog:
npx conventional-changelog -p angular -i CHANGELOG.md -s

Listing and inspecting tags

git tag                       # list all
git tag -l 'v1.*'             # filter
git show v1.4.0                # tagger info + commit details
git tag --contains <sha>       # which tags include this commit?
git describe --tags HEAD       # nearest tag (handy in CI)

Tag protection

On GitHub or GitLab, configure tag protection rules so only release pipelines can create tags matching v*. This prevents accidental retags.

Deleting and moving tags

git tag -d v1.4.0
git push origin --delete v1.4.0
# Re-create at a new commit:
git tag -a v1.4.0 -m "Release 1.4.0" <new-sha>
git push origin v1.4.0

Avoid this on published tags - downstream consumers may have pinned the SHA.

The pipeline contract

Make your CI's tag pipeline the only path to production. Manual npm publish from a developer laptop is the historical cause of countless "wrong version shipped" incidents. Tag, push, watch CI - that is the contract.