# 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/` or `` - Branch from `main` - Merge into `main` - Short-lived (hours to days, not weeks) - Deleted after merge **Fix branches**: `fix/` or `bugfix/` - Branch from `main` - Merge into `main` - Deleted after merge **Hotfix branches**: `hotfix/-` (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/` (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**: `/` **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: [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 `master` → `main` - 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 - [Trunk-Based Development](https://trunkbaseddevelopment.com/) - Pattern we primarily follow - [GitHub Flow](https://guides.github.com/introduction/flow/) - Simplified flow (close to ours) - [Git Flow](https://nvie.com/posts/a-successful-git-branching-model/) - More complex model (not adopted) - [GitLab Flow](https://docs.gitlab.com/ee/topics/gitlab_flow.html) - Hybrid approach ### Branch Naming - [GitHub Renaming](https://github.com/github/renaming) - Main branch renaming initiative - [Git Branch Naming](https://deepsource.io/blog/git-branch-naming-conventions/) - Naming conventions ### Versioning Integration - [Semantic Versioning](https://semver.org/) - Version numbering - [Git Tagging](https://git-scm.com/book/en/v2/Git-Basics-Tagging) - Tag documentation ### Internal Documentation - [ADR-008: Versioning Strategy](/home/phil/Projects/starpunk/docs/decisions/ADR-008-versioning-strategy.md) - Semantic versioning decision - [Versioning Strategy](/home/phil/Projects/starpunk/docs/standards/versioning-strategy.md) - Complete versioning spec - [Git Branching Strategy](/home/phil/Projects/starpunk/docs/standards/git-branching-strategy.md) - Complete branching spec - [Development Setup](/home/phil/Projects/starpunk/docs/standards/development-setup.md) - Development workflow --- **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