QA Engineer Skills 2026QA-2026Tagging and Releases

Tagging and Releases

Why Tags Matter for QA

Tags mark specific points in Git history -- typically releases. For QA engineers, tags create an audit trail: which commit was released, what was tested, and what the test results were. When a customer reports a bug on "version 2.4.0," you can check out that exact tag and reproduce the issue.


Creating Tags

Lightweight Tags

A lightweight tag is just a pointer to a commit. It has no additional metadata.

# Create a lightweight tag
git tag v2.4.0

# Tag a specific commit (not HEAD)
git tag v2.4.0 abc123f

Annotated Tags (Recommended)

Annotated tags store the tagger's name, date, and a message. For releases, always use annotated tags.

# Create an annotated tag
git tag -a v2.4.0 -m "Release 2.4.0 - passed full regression suite"

# Create an annotated tag with detailed test information
git tag -a v2.4.0 -m "Release 2.4.0
Regression suite: 342/342 passed
Browser coverage: Chrome 120, Firefox 121, Safari 17
CI run: https://github.com/org/repo/actions/runs/12345
Known issues: SHOP-567 (low priority, cosmetic)"

Working with Tags

# List all tags
git tag

# List tags matching a pattern
git tag -l "v2.4.*"

# Show tag details (annotated tags include the message)
git show v2.4.0

# Push a specific tag to remote
git push origin v2.4.0

# Push all tags
git push origin --tags

# Delete a local tag
git tag -d v2.4.0-rc1

# Delete a remote tag
git push origin --delete v2.4.0-rc1

# Checkout a specific tag (detached HEAD state)
git checkout v2.4.0

# Create a branch from a tag (for hotfixes)
git checkout -b hotfix/2.4.1 v2.4.0

Semantic Versioning

Most projects use semantic versioning (SemVer): MAJOR.MINOR.PATCH

Component When to Increment Example
MAJOR Breaking changes (API incompatible) v2.0.0 to v3.0.0
MINOR New features (backward compatible) v2.3.0 to v2.4.0
PATCH Bug fixes (backward compatible) v2.4.0 to v2.4.1

Pre-release tags indicate versions that are not yet stable:

git tag -a v2.4.0-rc1 -m "Release candidate 1 for 2.4.0"
git tag -a v2.4.0-beta.1 -m "Beta 1 for 2.4.0"
git tag -a v2.4.0-alpha.3 -m "Alpha 3 for 2.4.0"

QA and Versioning

Version Stage QA Activity
Alpha Exploratory testing, feature-level tests
Beta Full regression, performance testing, cross-browser
Release Candidate Final regression, sign-off checklist, no new features
Release Smoke tests on production, monitoring

Associating Test Results with Releases

The gold standard is a release process where test results are permanently linked to the release tag.

In the Tag Message

git tag -a v2.4.0 -m "Release 2.4.0

Test Results:
  Unit tests: 1,247/1,247 passed
  Integration tests: 89/89 passed
  Browser tests: 342/342 passed (Chrome 120, Firefox 121, Safari 17)
  Visual regression: 0 diffs detected
  Performance: LCP 1.2s (budget: 2.5s), FID 45ms (budget: 100ms)

CI Run: https://github.com/org/repo/actions/runs/12345
Test Report: https://qa-reports.example.com/releases/2.4.0

Known Issues:
  SHOP-567: Tooltip misalignment on mobile (low priority)
  SHOP-589: Slow search on large datasets (medium, fix planned for 2.5.0)"

In GitHub Releases

GitHub Releases provide a richer interface than raw tags. You can add formatted release notes, attach binary artifacts, and mark pre-releases.

# Create a GitHub release from a tag
gh release create v2.4.0 \
  --title "Release 2.4.0" \
  --notes "## What's New
- Redesigned checkout flow
- Added PayPal support
- Fixed 12 bugs from 2.3.x

## Test Results
- Full regression: 342/342 passed
- [CI Run](https://github.com/org/repo/actions/runs/12345)
- [Test Report](https://qa-reports.example.com/releases/2.4.0)

## Known Issues
- SHOP-567: Tooltip misalignment on mobile"

In CI/CD Pipeline (Automated)

The best approach: automate release tagging as part of the pipeline.

# Tag and release after all tests pass
create-release:
  needs: [unit-tests, integration-tests, browser-tests]
  if: github.ref == 'refs/heads/main' && github.event_name == 'push'
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v4

    - name: Determine version
      id: version
      run: echo "VERSION=$(cat package.json | jq -r .version)" >> $GITHUB_OUTPUT

    - name: Create tag
      run: |
        git tag -a "v${{ steps.version.outputs.VERSION }}" \
          -m "Release ${{ steps.version.outputs.VERSION }} - all tests passed"
        git push origin "v${{ steps.version.outputs.VERSION }}"

Release Workflow for QA

A typical QA-involved release workflow:

  1. Feature freeze: No new features on the release branch. Only bug fixes.
  2. Run full regression: Execute the complete test suite (automated + manual exploratory).
  3. Document results: Update the release checklist with test results.
  4. Create release candidate tag: v2.4.0-rc1
  5. Deploy RC to staging: Smoke test in a production-like environment.
  6. Sign-off: QA approves the release based on defined criteria.
  7. Tag the release: v2.4.0 with test result metadata.
  8. Deploy to production: Run post-deploy smoke tests.
  9. Monitor: Watch error rates and performance metrics for 24-48 hours.

Comparing Releases

Git makes it easy to see what changed between releases -- essential for writing test plans.

# See all commits between two releases
git log v2.3.0..v2.4.0 --oneline

# See the diff between two releases
git diff v2.3.0..v2.4.0

# See which files changed
git diff v2.3.0..v2.4.0 --stat

# See commits that touched test files
git log v2.3.0..v2.4.0 -- tests/

This helps you answer: "What changed since the last release?" -- the first question in any regression test planning session.


Hands-On Exercise

  1. Create an annotated tag for a "release" with test result metadata in the message
  2. Push the tag and create a GitHub Release with formatted release notes
  3. Practice checking out a tag and creating a hotfix branch from it
  4. Use git log v1..v2 to compare two releases and identify what needs regression testing
  5. Set up an automated release tag in your CI pipeline that runs after all tests pass
  6. Write a release sign-off checklist that your team can use for every release