How to Create a New Version in Git

This guide walks you through creating new versions/releases for the build-certs project using proper git workflows.

Quick Reference

# 1. Prepare for release
git status                    # Check current state
git add .                     # Stage changes
git commit -m "message"       # Commit changes

# 2. Create and tag version
git tag -a v2.1.0 -m "Version 2.1.0 - Description"
git push origin main          # Push commits
git push origin v2.1.0        # Push tag

# 3. Update version info in files
# Edit build-certs.sh header
# Update CHANGELOG.md
# Update README.md if needed

Detailed Step-by-Step Process

Step 1: Prepare Your Changes

  1. Check current status:

    git status
    git log --oneline -5      # See recent commits
    
  2. Make sure you’re on the right branch:

    git branch                # See current branch
    git checkout main         # Switch to main if needed
    
  3. Test your changes:

    ./build-certs.sh --help   # Test basic functionality
    ./build-certs.sh freepbx.conf  # Test certificate generation
    

Step 2: Update Version Information

  1. Update the script header in build-certs.sh:

    # Change from:
    # build-certs.sh v2.0
    # To:
    # build-certs.sh v2.1.0
    
  2. Update CHANGELOG.md (add new section at top):

    ## Version 2.1.0 (2025-10-XX)
    
    ### New Features
    - Added feature X
    - Improved feature Y
    
    ### Bug Fixes
    - Fixed issue with Z
    
    ### Changes
    - Updated documentation
    
  3. Update README.md if there are significant changes:

    # build-certs.sh v2.1.0 — README
    

Step 3: Commit Your Changes

  1. Stage all changes:

    git add .
    # Or be selective:
    git add build-certs.sh CHANGELOG.md README.md
    
  2. Commit with descriptive message:

    git commit -m "Prepare version 2.1.0 release
    
    - Add new feature X
    - Fix bug Y
    - Update documentation
    - Bump version to 2.1.0"
    

Step 4: Create Version Tag

  1. Create annotated tag:

    git tag -a v2.1.0 -m "Version 2.1.0 - Brief description of main changes
    
    - Major feature or fix
    - Other important changes
    - Any breaking changes or notes"
    
  2. Verify tag was created:

    git tag -l                # List all tags
    git show v2.1.0          # Show tag details
    

Step 5: Push Everything

  1. Push commits:

    git push origin main
    
  2. Push tags:

    git push origin v2.1.0    # Push specific tag
    # OR
    git push origin --tags    # Push all tags
    

Step 6: Verify Release

  1. Check remote repository:

    git ls-remote --tags origin  # See all remote tags
    
  2. Test clean checkout:

    # In a different directory:
    git clone /path/to/your/repo test-checkout
    cd test-checkout
    git checkout v2.1.0
    ./build-certs.sh --help
    

Version Numbering Guidelines

Use Semantic Versioning: MAJOR.MINOR.PATCH

  • MAJOR (v3.0.0): Breaking changes, major rewrites

  • MINOR (v2.1.0): New features, backwards compatible

  • PATCH (v2.0.1): Bug fixes, backwards compatible

Examples for build-certs

  • v2.0.1: Fix typo in help text

  • v2.1.0: Add new --list-certs option

  • v3.0.0: Change command-line argument format

Working with Branches (Advanced)

Feature Branch Workflow

  1. Create feature branch:

    git checkout -b feature/new-validation
    # Make changes...
    git add .
    git commit -m "Add certificate validation feature"
    
  2. Merge to main:

    git checkout main
    git merge feature/new-validation
    git branch -d feature/new-validation  # Delete feature branch
    
  3. Then follow normal versioning steps

Release Branch Workflow

  1. Create release branch:

    git checkout -b release/v2.1.0
    # Update version numbers, changelog, etc.
    git commit -m "Prepare v2.1.0 release"
    
  2. Merge to main and tag:

    git checkout main
    git merge release/v2.1.0
    git tag -a v2.1.0 -m "Version 2.1.0"
    git push origin main
    git push origin v2.1.0
    

Version Control Workflows

Different projects benefit from different branching strategies. Here are the most common approaches:

Version Branch Workflow

When to use: Major version development, long development cycles

# Create version branch for major development
git checkout -b version2
# ... develop multiple features for v2.0 ...
git commit -m "Rewrite certificate generation"
git commit -m "Add new ECC curves"
git commit -m "Improve error handling"
git commit -m "Update documentation"

# When v2.0 development is complete
git checkout main
git merge version2
git tag -a v2.0.0 -m "Version 2.0.0 - Major rewrite"
git push origin main
git push origin v2.0.0

# Option: Keep version2 branch for future v2.x work
# Or delete it: git branch -d version2

Pros: Isolates major version work, clear development focus
Cons: Can diverge significantly from main, large merges

Release Branch Workflow (GitFlow Style)

When to use: Formal release process, multiple environments, complex projects

# Normal development on main
git commit -m "Add feature A"
git commit -m "Add feature B"

# When ready to prepare release
git checkout -b release/v2.1.0
# ... make release-specific changes ...
vim build-certs.sh     # Update version number
vim CHANGELOG.md       # Add release notes
git commit -m "Prepare v2.1.0 release"

# Optional: Continue bug fixes on release branch
git commit -m "Fix last-minute bug"

# When release is ready
git checkout main
git merge release/v2.1.0
git tag -a v2.1.0 -m "Version 2.1.0"
git push origin main
git push origin v2.1.0
git branch -d release/v2.1.0  # Clean up

Pros: Dedicated release preparation, hotfix capability
Cons: Most complex, overhead for small projects

Choosing the Right Workflow

For build-certs Project

Based on your project characteristics:

Current State: Solo development, shell script, certificate tool
Recommendation: Feature Branch Workflow or Simple Workflow

Simple Workflow (Current Approach)

# Continue as you have been
git add .
git commit -m "Improve certificate validation"
git tag -a v2.1.0 -m "Version 2.1.0"
git push origin main && git push origin v2.1.0

Decision Matrix

Workflow

Project Size

Team Size

Release Frequency

Complexity

Simple

Small

1

Any

Low

Feature Branch

Any

1-5

Regular

Medium

Version Branch

Large

Any

Major versions

Medium

Release Branch

Enterprise

5+

Formal process

High

Practical Examples

Example 1: Adding New Feature with Feature Branch

# Current state: v2.1.0 released
git checkout main
git pull origin main

# Start new feature
git checkout -b feature/dry-run-mode
echo "# Add --dry-run option" >> TODO.md
git add TODO.md
git commit -m "Plan dry-run feature"

# Implement feature
vim build-certs.sh  # Add dry-run functionality
git add build-certs.sh
git commit -m "Add --dry-run option for testing"

# Test and refine
git commit -m "Fix dry-run output formatting"
git commit -m "Add dry-run tests"

# Feature complete - merge to main
git checkout main
git merge feature/dry-run-mode
git branch -d feature/dry-run-mode

# Prepare release
git checkout -b prepare-v2.2.0
vim build-certs.sh CHANGELOG.md README.md
git add .
git commit -m "Prepare v2.2.0 release - Add dry-run mode"

# Release
git checkout main
git merge prepare-v2.2.0
git tag -a v2.2.0 -m "Version 2.2.0 - Add dry-run testing mode"
git push origin main
git push origin v2.2.0
git branch -d prepare-v2.2.0

Example 2: Version Branch for Major Rewrite

# Current state: v2.1.1 released
git checkout main

# Start version 3.0 development (breaking changes)
git checkout -b version3
echo "# v3.0 Planning" > V3_PLAN.md
git add V3_PLAN.md
git commit -m "Start v3.0 planning"

# Major development work
git commit -m "Rewrite config parser for YAML support"
git commit -m "Add plugin architecture"
git commit -m "Breaking: Change command line interface"
git commit -m "Add comprehensive test suite"

# Continue development over weeks/months...
git commit -m "Update all documentation for v3.0"
git commit -m "Final v3.0 testing and validation"

# When v3.0 is ready
git checkout main
git merge version3
git tag -a v3.0.0 -m "Version 3.0.0 - Major rewrite with breaking changes"
git push origin main
git push origin v3.0.0

# Keep version3 branch for future v3.x maintenance
# Or delete: git branch -d version3

Best Practices

Branch Naming Conventions

# Feature branches
feature/add-validation
feature/improve-logging  
feature/yaml-config

# Version branches
version2
version3
v2-development

# Release branches
release/v2.1.0
release/v3.0.0-rc1

# Hotfix branches
hotfix/security-fix
hotfix/critical-bug

Commit Message Patterns

# Feature development
git commit -m "Add certificate validation logic"
git commit -m "Improve error messages in validation"
git commit -m "Add tests for validation feature"

# Release preparation
git commit -m "Prepare v2.1.0 release"
git commit -m "Update version to v2.1.0"
git commit -m "Add v2.1.0 changelog entries"

# Maintenance
git commit -m "Fix typo in help text"
git commit -m "Update documentation links"

Merge vs. Rebase

# Merge (preserves feature branch history)
git checkout main
git merge feature/new-validation

# Rebase (linear history, cleaner)
git checkout feature/new-validation
git rebase main
git checkout main
git merge feature/new-validation  # Fast-forward merge

Common Scenarios

Fixing a Bug in Released Version

# Make the fix
git add .
git commit -m "Fix critical bug in certificate validation"

# Create patch version
git tag -a v2.0.1 -m "Version 2.0.1 - Fix certificate validation bug"
git push origin main
git push origin v2.0.1

Adding a New Feature

# Implement feature
git add .
git commit -m "Add --dry-run option for testing certificate generation"

# Update version info files (build-certs.sh, CHANGELOG.md)
git add .
git commit -m "Prepare v2.1.0 release - Add dry-run option"

# Create minor version
git tag -a v2.1.0 -m "Version 2.1.0 - Add dry-run testing option"
git push origin main
git push origin v2.1.0

Emergency Hotfix

# Create hotfix branch from latest tag
git checkout v2.0.0
git checkout -b hotfix/critical-security-fix

# Make fix
git add .
git commit -m "Fix security vulnerability in certificate validation"

# Merge back to main
git checkout main
git merge hotfix/critical-security-fix

# Create patch release
git tag -a v2.0.1 -m "Version 2.0.1 - Security fix"
git push origin main
git push origin v2.0.1

Troubleshooting

Mistake in Tag

# Delete local tag
git tag -d v2.1.0

# Delete remote tag
git push origin :refs/tags/v2.1.0

# Create new tag
git tag -a v2.1.0 -m "Corrected version message"
git push origin v2.1.0

Forgot to Update Version Numbers

# Make the updates
vim build-certs.sh CHANGELOG.md

# Amend the last commit (if not pushed yet)
git add .
git commit --amend -m "Prepare v2.1.0 release with version updates"

# Re-create tag
git tag -d v2.1.0
git tag -a v2.1.0 -m "Version 2.1.0 - Complete release"

Check What Changed Since Last Version

# See commits since last tag
git log v2.0.0..HEAD --oneline

# See file changes since last tag
git diff v2.0.0..HEAD --name-only

# Detailed diff since last tag
git diff v2.0.0..HEAD

Automation Ideas

Simple Release Script

Create scripts/release.sh:

#!/bin/bash
VERSION="$1"
if [ -z "$VERSION" ]; then
    echo "Usage: $0 v2.1.0"
    exit 1
fi

echo "Creating release $VERSION"
git add .
git commit -m "Prepare $VERSION release"
git tag -a "$VERSION" -m "Version $VERSION"
git push origin main
git push origin "$VERSION"
echo "Release $VERSION created!"

Usage: ./scripts/release.sh v2.1.0

Git Configuration for Modern Workflows

Setting Up Default Branch as ‘main’

To ensure all new repositories use main instead of master by default:

On Git Server (git@devel)

# Set global default branch for new repositories
git config --global init.defaultBranch main

# Verify configuration
git config --global --list | grep defaultBranch

On All Client Machines (VS Code, development hosts)

# Set global default branch for new repositories
git config --global init.defaultBranch main

# Verify configuration
git config --global --list | grep defaultBranch

For New Bare Repositories

When creating new bare repositories on the server:

# Create bare repository with main as default
git init --bare new-project.git
cd new-project.git
git symbolic-ref HEAD refs/heads/main  # Explicitly set default branch

Viewing Git Configuration

# Show all Git configuration (global + local + system)
git config --list

# Show only global configuration
git config --global --list

# Show only local repository configuration  
git config --local --list

# Show where each setting comes from
git config --list --show-origin

# Show specific settings
git config user.name
git config user.email
git config init.defaultBranch

What This Configuration Does

  • New Local Repos: git init creates repositories with main branch

  • New Bare Repos: Server repositories default to main branch

  • First Push: When you push to a new bare repo, main becomes the default

  • Clones: New clones automatically check out the main branch

  • Consistency: All team members get the same branch naming

Verification

Test that your configuration works:

# Test local repository creation
git init test-repo
cd test-repo
git branch  # Should show 'main' after first commit

# Test bare repository creation (on server)
git init --bare test-bare.git
cd test-bare.git
git symbolic-ref HEAD  # Should show 'refs/heads/main'

This guide should help you create consistent, professional releases for your build-certs project!