Skip to main content

Git Integration

Versionator integrates with Git to create annotated tags and release branches for your versions.

Creating Releases

The release command creates an annotated Git tag and release branch for the current version:

# Bump version and release
versionator patch increment
versionator release
# Creates: tag v1.0.0 and branch release/v1.0.0

# With custom message
versionator release -m "Release 1.0.0 with new features"

# Force overwrite existing tag
versionator release --force

Auto-Commit Behavior

The release command will automatically commit the VERSION file if:

  • The working directory is dirty
  • The VERSION file is the only dirty file

This enables a clean workflow:

versionator patch increment    # VERSION file is now dirty
versionator release # Auto-commits VERSION, creates tag and branch

If other files are dirty, the command will fail with a list of dirty files.

Tag Naming

The tag name follows your version format:

VERSION FileTag Created
1.0.01.0.0
v1.0.0v1.0.0
V1.0.0V1.0.0
v1.0.0-beta.1v1.0.0-beta.1

Release Branches

By default, versionator release creates both a tag and a release branch:

versionator release
# Output:
# Committed VERSION file: Release 1.0.0
# Successfully created tag 'v1.0.0' for version 1.0.0 using git
# Successfully created branch 'release/v1.0.0'

Why Release Branches?

Release branches serve important purposes:

  • Hotfix isolation: Apply patches to a specific release without pulling in main branch changes
  • Support multiple versions: Maintain release/v1.x and release/v2.x simultaneously
  • CI/CD triggers: Many pipelines trigger on release/* branch patterns
  • Clear release history: Each release has a named branch for easy navigation

Configuration

Configure release branches in .versionator.yaml:

release:
createBranch: true # Enable/disable (default: true)
branchPrefix: "release/" # Prefix for branch names

What Gets Created

VERSIONTagBranch
1.0.0v1.0.0release/v1.0.0
1.0.0-beta.1v1.0.0-beta.1release/v1.0.0-beta.1
2.0.0-rc.1v2.0.0-rc.1release/v2.0.0-rc.1

Skip Branch Creation

For a single invocation:

versionator release --no-branch

To disable globally:

# .versionator.yaml
release:
createBranch: false

Pushing to Remote

Tags and branches are local by default. Push them to your remote:

# Push specific tag
git push origin v1.0.0

# Push all tags
git push --tags

# Push tag and release branch
git push origin v1.0.0
git push origin release/v1.0.0

Version Bump Workflow

A typical release workflow with versionator:

# 1. Make sure other changes are committed
git status

# 2. Bump version and release
versionator minor increment
versionator release

# 3. Push everything
git push
git push --tags
git push origin release/v1.1.0

The release command handles the VERSION file commit automatically.

Pre-release Workflow

For pre-release versions:

# Set pre-release
versionator config prerelease set alpha.1
versionator release

# Iterate on alpha
versionator config prerelease set alpha.2
versionator release

# Move to beta
versionator config prerelease set beta.1
versionator release

# Final release
versionator config prerelease clear
versionator release
git push --tags

Semantic Commit Automation

Versionator can automatically determine version bumps by analyzing commit messages since the last tag, similar to semantic-release.

The bump Command

The bump command parses commits and determines the appropriate version bump:

# Analyze commits and bump version automatically
versionator bump

# Preview what would happen without making changes
versionator bump --dry-run

# Only use +semver: markers
versionator bump --mode=semver

# Only use conventional commits
versionator bump --mode=conventional

Supported Commit Formats

+semver: markers (can appear anywhere in commit message):

MarkerEffect
+semver:majorBump major (1.0.0 → 2.0.0)
+semver:minorBump minor (1.0.0 → 1.1.0)
+semver:patchBump patch (1.0.0 → 1.0.1)
+semver:skipSkip version bump entirely

Conventional Commits (conventionalcommits.org):

Commit TypeEffect
feat: ...Bump minor
fix: ...Bump patch
feat!: ...Bump major (breaking)
BREAKING CHANGE: in footerBump major

Conflict Resolution

  • Highest bump level wins (major > minor > patch)
  • +semver:skip takes precedence and prevents any bump

Automated Release Workflow

Combine bump and release for a fully automated workflow:

# After merging feature branches to main
versionator bump && versionator release && git push && git push --tags

Lefthook Post-Merge Automation

Automate releases after merging to main with Lefthook:

# lefthook.yml
post-merge:
commands:
auto-release:
run: |
# Only run on main branch
if [ "$(git branch --show-current)" = "main" ]; then
versionator bump --dry-run
if [ $? -eq 0 ]; then
versionator bump && versionator release && git push && git push --tags
fi
fi

CI Workflow (GitHub Actions)

For teams that prefer CI-based releases:

name: Auto Release

on:
push:
branches: [main]

jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Need full history for commit analysis

- name: Install versionator
run: go install github.com/benjaminabbitt/versionator@latest

- name: Check for version bump
id: bump
run: |
if versionator bump --dry-run 2>&1 | grep -q "Would bump"; then
echo "should_release=true" >> $GITHUB_OUTPUT
else
echo "should_release=false" >> $GITHUB_OUTPUT
fi

- name: Bump and Release
if: steps.bump.outputs.should_release == 'true'
run: |
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
versionator bump
versionator release
git push
git push --tags

Example Workflow

# Developer workflow with conventional commits
git commit -m "feat: add user authentication"
git commit -m "fix: resolve login timeout issue"
git commit -m "feat!: redesign API endpoints" # Breaking change

# Merge to main, then release
git checkout main
git merge feature-branch

# Versionator analyzes commits and bumps appropriately
versionator bump --dry-run
# Output: Would bump from 1.2.3 to 2.0.0 (major)
# Triggering commit: feat!: redesign API endpoints

versionator bump
versionator release
git push && git push --tags

Template Variables from Git

Versionator extracts information from Git for templates:

VariableDescription
{{Hash}}Full commit hash
{{ShortHash}}7-character hash
{{MediumHash}}12-character hash
{{BranchName}}Current branch name
{{EscapedBranchName}}Branch with / replaced by -
{{CommitsSinceTag}}Commits since last tag
{{CommitAuthor}}Commit author name
{{CommitAuthorEmail}}Commit author email
{{CommitDate}}Commit timestamp (ISO 8601)
{{Dirty}}Non-empty if uncommitted changes
{{UncommittedChanges}}Count of uncommitted files

Git Hooks Integration

Integrate versionator with Git hooks:

Pre-commit Hook

Ensure VERSION file is valid:

#!/bin/bash
# .git/hooks/pre-commit

# Validate VERSION file format
if ! versionator output version > /dev/null 2>&1; then
echo "ERROR: Invalid VERSION file"
exit 1
fi

Post-merge Hook

Regenerate version files after merge:

#!/bin/bash
# .git/hooks/post-merge

# Regenerate version file for interpreted languages
versionator output emit python --output src/_version.py

Lefthook Integration

With Lefthook:

# lefthook.yml
pre-commit:
commands:
version-check:
run: versionator output version > /dev/null
fail_text: "Invalid VERSION file"

post-merge:
commands:
version-emit:
run: versionator output emit python --output src/_version.py

GitHub Actions Integration

See CI/CD Integration for detailed GitHub Actions workflows.

Best Practices

  1. Use release command: Let versionator release handle VERSION commits
  2. Clean working directory: Commit other changes before bumping version
  3. Semantic commits: Use descriptive commit messages for version bumps
  4. Push tags explicitly: Tags don't push automatically with git push
  5. Use annotated tags: Versionator creates annotated tags by default

See Also