Files
StarPunk/docs/decisions/ADR-009-git-branching-strategy.md
2025-11-18 19:21:31 -07:00

14 KiB

ADR-009: Git Branching Strategy

Status

Accepted

Context

StarPunk needs a git branching strategy that supports:

  1. Semantic versioning workflow - Moving from 0.x.y development through 1.0.0 stable release
  2. Single developer initially - Optimized for solo work but scalable to small teams
  3. Clean release history - Clear tags and versioning aligned with SemVer
  4. Hotfix capability - Ability to patch production releases
  5. Minimal complexity - Appropriate for indie project scale
  6. Development discipline - Structure without bureaucracy

Current State

The project just renamed its primary branch from master to main to align with modern Git conventions and industry best practices. This is a brand new repository with no commits yet, currently at version 0.1.0 (development phase).

Requirements

The branching strategy must:

  1. Support semantic versioning releases (0.1.0 → 1.0.0 → 1.0.1 → 1.1.0 → 2.0.0)
  2. Work for solo and team development
  3. Enable clean releases with proper tagging
  4. Allow hotfixes to production versions
  5. Keep main branch stable - always in working state
  6. Minimize long-lived branches - integrate frequently
  7. Align with IndieWeb values - simplicity, no lock-in
  8. Be well-documented - clear workflows for common scenarios

Decision

We will adopt a simplified trunk-based development strategy with feature branches and semantic versioning integration.

Core Principles

  1. Single primary branch: main
  2. Branch name: main (not master)
  3. Feature branches: Short-lived branches for features/fixes
  4. Direct tagging: Tag main for releases
  5. Hotfix branches: For production patches (post-1.0.0)
  6. No long-lived branches: Integrate to main frequently
  7. Annotated tags: Always use annotated tags for releases

Branch Structure

Primary branch: main

  • Single source of truth
  • Always stable (tests pass)
  • Tagged for releases
  • Protected from force push
  • Never rewritten

Feature branches: feature/<description> or <description>

  • Branch from main
  • Merge into main
  • Short-lived (hours to days, not weeks)
  • Deleted after merge

Fix branches: fix/<description> or bugfix/<description>

  • Branch from main
  • Merge into main
  • Deleted after merge

Hotfix branches: hotfix/<version>-<description> (post-1.0.0 only)

  • Branch from release tag (e.g., v1.0.0)
  • Fix critical production bugs
  • Tagged as new patch release (e.g., v1.0.1)
  • Merged into main
  • Deleted after release

Release branches: release/<version> (optional, rarely used)

  • Only if release preparation requires multiple commits
  • For V1, likely unnecessary (prepare on main or feature branch)
  • Branch from main, merge back to main, tag, delete

Branch Naming Conventions

Preferred format: <type>/<description>

Types:

  • feature/ - New features
  • fix/ or bugfix/ - Bug fixes
  • hotfix/ - Production hotfixes
  • docs/ - Documentation only
  • refactor/ - Code refactoring
  • test/ - Test additions
  • chore/ - Maintenance tasks

Description:

  • Lowercase with hyphens
  • Descriptive but concise
  • Example: feature/micropub-endpoint, fix/rss-timezone

Alternative: Simple description without prefix (e.g., micropub-endpoint)

Tagging Strategy

Format: vMAJOR.MINOR.PATCH[-PRERELEASE]

Type: Annotated tags (always)

Examples:

  • v0.1.0 - Development release
  • v1.0.0 - First stable release
  • v1.0.1 - Patch release
  • v1.0.0-alpha.1 - Pre-release

Tag message format:

Release MAJOR.MINOR.PATCH: <Brief description>

[Optional details]

Workflows

Development (0.x.y):

  1. Work on main or feature branches
  2. Commit frequently
  3. Tag development milestones (v0.1.0, v0.2.0)
  4. Breaking changes allowed

Stable releases (1.0.0+):

  1. Prepare release on main
  2. Update version and changelog
  3. Commit version bump
  4. Create annotated tag
  5. Push main and tag

Hotfixes (post-1.0.0):

  1. Branch from release tag
  2. Fix bug
  3. Update version and changelog
  4. Tag new patch version
  5. Merge to main
  6. Push main and tag
  7. Delete hotfix branch

Rationale

Why Simplified Trunk-Based Development?

Trunk-based development means developers integrate to a single branch (main) frequently, using short-lived feature branches.

Pros:

  1. Simple - One primary branch, minimal overhead
  2. Scalable - Works for solo and small teams
  3. Fast integration - Reduces merge conflicts
  4. Always releasable - Main stays stable
  5. Aligns with CI/CD - Easy to automate testing
  6. Reduces complexity - No long-lived branches to manage

Fits StarPunk because:

  • Personal project optimized for simplicity
  • Small codebase, infrequent releases
  • Solo developer initially
  • No need for complex branching

Why Main Instead of Master?

Decision: Use main as primary branch name

Rationale:

  1. Industry standard - GitHub, GitLab default since 2020
  2. Inclusive language - Removes potentially offensive terminology
  3. Aligns with modern practices - Most new projects use main
  4. Clear semantics - "Main" clearly indicates primary branch
  5. No functional difference - Just a name, but better name

Migration:

  • Project just renamed mastermain
  • All documentation uses main consistently

Why Not Git Flow?

Git Flow is a popular branching model with main, develop, release, hotfix, and feature branches.

Considered but rejected:

Pros:

  • Well-defined process
  • Clear separation of development and production
  • Structured release process

Cons:

  • Too complex for indie project
  • Overhead - Multiple long-lived branches
  • Slow integration - Features merge to develop, not main
  • Designed for scheduled releases, not continuous delivery
  • Overkill for single developer

Conclusion: Git Flow's complexity doesn't justify benefits for StarPunk's scale

Why Not GitHub Flow?

GitHub Flow is a simpler model: just main and feature branches, deploy from main.

Very close to our choice:

Pros:

  • Simple - only main + feature branches
  • Fast - deploy anytime
  • Works well with pull requests

Differences from our approach:

  • GitHub Flow deploys directly from main
  • We tag releases on main instead
  • We add hotfix branches for production patches

Conclusion: We essentially use GitHub Flow + semantic versioning + hotfix branches

Why Annotated Tags?

Annotated vs lightweight tags:

Annotated tags (chosen):

  • Contain metadata (tagger, date, message)
  • Can include release notes
  • Can be GPG signed
  • Treated as full Git objects
  • Required: git tag -a v1.0.0 -m "Release 1.0.0"

Lightweight tags (rejected):

  • Just pointers to commits
  • No metadata
  • Created: git tag v1.0.0

Decision: Always use annotated tags for releases

  • Provides complete release history
  • Can include release notes in tag message
  • Better for professional releases

Why Feature Branches?

Alternatives:

  1. Direct commits to main - Fast but risky
  2. Feature branches - Slight overhead but safer
  3. Pull request workflow - Most structured

Decision: Use feature branches with flexible merge approach

For solo development:

  • Feature branches optional for small changes
  • Required for larger features
  • Merge directly without pull request

For team development:

  • Feature branches required
  • Pull request review before merge
  • Delete branch after merge

Benefits:

  • Isolates work in progress
  • Enables experimentation
  • Keeps main stable
  • Scalable to team workflow

Consequences

Positive

  1. Simple to understand - One primary branch, clear workflows
  2. Scalable - Works solo, scales to small teams
  3. Fast integration - Short-lived branches reduce conflicts
  4. Clean history - Clear tags for every release
  5. Semantic versioning alignment - Tag strategy matches SemVer
  6. Hotfix capability - Can patch production releases
  7. Low overhead - No complex branch management
  8. Standard practices - Uses modern Git conventions
  9. Well-documented - Clear workflows for common scenarios
  10. Flexible - Can use pull requests or direct merges

Negative

  1. Discipline required - Main must stay stable (tests must pass)
  2. Manual version management - Must update version, changelog, tag (for V1)
  3. Solo optimization - Strategy favors individual over large team
  4. No develop buffer - Changes go directly to main (requires good testing)

Neutral

  1. Feature branch discipline - Must keep branches short-lived
  2. Test coverage important - Main stability depends on testing
  3. Rebase vs merge - Team must choose and be consistent

Mitigations

For main stability:

  • Run tests before merging
  • Use pull requests for team development
  • Establish branch protection rules when team grows

For version management:

  • Document clear release process
  • Create release checklist
  • Consider automation in V2+ if needed

For long-lived branches:

  • Review open branches weekly
  • Delete stale branches
  • Encourage frequent integration

Implementation

Immediate Actions

  1. Primary branch: Already renamed to main
  2. Create documentation: docs/standards/git-branching-strategy.md
  3. Update all references: Ensure docs use main consistently
  4. Initial tag: Tag current state as v0.1.0

Branch Protection (Future)

When team grows or project matures, add GitHub branch protection:

Settings → Branches → Add rule for main:
- Require pull request reviews (1 approval)
- Require status checks to pass
- Prevent force push
- Prevent deletion

For solo development: Self-discipline instead of enforced rules

Release Process

Development releases (0.x.y):

  1. Update starpunk/__init__.py version
  2. Update CHANGELOG.md
  3. Commit: git commit -m "Bump version to 0.x.y"
  4. Tag: git tag -a v0.x.y -m "Development release 0.x.y"
  5. Push: git push origin main v0.x.y

Stable releases (1.0.0+):

  1. Update version and changelog
  2. Commit version bump
  3. Tag: git tag -a v1.0.0 -m "Release 1.0.0: First stable release"
  4. Push: git push origin main v1.0.0

Hotfixes:

  1. Branch: git checkout -b hotfix/1.0.1-fix v1.0.0
  2. Fix bug and update version
  3. Tag: git tag -a v1.0.1 -m "Hotfix 1.0.1: Bug fix"
  4. Merge: git checkout main && git merge hotfix/1.0.1-fix
  5. Push: git push origin main v1.0.1
  6. Delete: git branch -d hotfix/1.0.1-fix

Documentation

Created comprehensive documentation:

  • Strategy document: docs/standards/git-branching-strategy.md
    • Branch types and naming
    • Workflows and examples
    • Best practices
    • Troubleshooting
  • This ADR: docs/decisions/ADR-009-git-branching-strategy.md
    • Decision rationale
    • Alternatives considered

Alternatives Considered

Alternative 1: Git Flow

Description: Use full Git Flow with main, develop, release, hotfix, feature branches

Pros:

  • Well-established pattern
  • Clear separation of development and production
  • Structured release process
  • Good for scheduled releases

Cons:

  • Too complex for indie project
  • Multiple long-lived branches
  • Slower integration
  • More overhead
  • Designed for different release model

Rejected: Complexity doesn't match project scale

Alternative 2: Trunk-Based Development (Pure)

Description: All commits directly to main, no feature branches

Pros:

  • Maximum simplicity
  • Fastest integration
  • No branch management

Cons:

  • Risky - broken commits go to main
  • No isolation for work in progress
  • Difficult for team collaboration
  • No experimentation space

Rejected: Too risky, doesn't scale to team

Alternative 3: GitHub Flow (Pure)

Description: main + feature branches, deploy from main continuously

Pros:

  • Simple and well-documented
  • Works well with pull requests
  • Fast deployment

Cons:

  • Designed for continuous deployment
  • Doesn't emphasize versioned releases
  • No hotfix branch pattern

Partially adopted: We use this + semantic versioning + hotfix branches

Alternative 4: Release Branches Primary

Description: Always use release branches, never tag main directly

Pros:

  • Clear release preparation phase
  • Can stabilize release while main continues

Cons:

  • Adds complexity
  • Creates long-lived branches
  • Overkill for small project

Rejected: Unnecessary complexity for V1

Alternative 5: Keep Master Branch Name

Description: Continue using master instead of main

Pros:

  • Traditional name
  • No migration needed
  • No functional difference

Cons:

  • Outdated convention
  • Out of step with industry
  • Potentially offensive terminology
  • New projects use main

Rejected: Modern standard is main, no reason not to adopt

References

Git Branching Models

Branch Naming

Versioning Integration

Internal Documentation


ADR: 009 Date: 2025-11-18 Status: Accepted Decision: Adopt simplified trunk-based development with main branch, feature branches, semantic versioning tags, and hotfix capability Supersedes: None