# 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 `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
