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

725 lines
16 KiB
Markdown

# Git Branching Strategy
## Overview
This document defines the git branching strategy for StarPunk. The strategy balances simplicity with discipline, appropriate for a personal/small-team project while supporting semantic versioning and clean releases.
**Philosophy**: Keep it simple. Minimize long-lived branches. Integrate frequently.
## Primary Branch
**Branch**: `main`
**Purpose**: The primary development branch and source of truth
**Characteristics**:
- Always contains the latest development code
- Should be stable and pass all tests
- Protected from direct commits (use pull requests)
- Tagged for releases
- Never rewritten or force-pushed
**Version state**: Development version (0.x.y) until first stable release (1.0.0)
## Branch Types
### Feature Branches
**Naming**: `feature/<description>` or `<description>`
**Purpose**: Develop new features or enhancements
**Lifecycle**:
- Branch from: `main`
- Merge into: `main`
- Delete after: Merged or abandoned
**Examples**:
- `feature/micropub-endpoint`
- `feature/rss-feed`
- `indieauth-integration`
- `note-markdown-support`
**Workflow**:
```bash
# Create feature branch
git checkout -b feature/micropub-endpoint main
# Work on feature
git add .
git commit -m "Add micropub endpoint skeleton"
# Keep updated with main
git fetch origin
git rebase origin/main
# When ready, create pull request or merge
git checkout main
git merge feature/micropub-endpoint
# Delete feature branch
git branch -d feature/micropub-endpoint
```
### Fix Branches
**Naming**: `fix/<description>` or `bugfix/<description>`
**Purpose**: Fix bugs in development code
**Lifecycle**:
- Branch from: `main`
- Merge into: `main`
- Delete after: Merged
**Examples**:
- `fix/slug-generation-unicode`
- `bugfix/rss-invalid-xml`
- `fix/auth-redirect-loop`
**Workflow**: Same as feature branches
### Hotfix Branches
**Naming**: `hotfix/<version>-<description>`
**Purpose**: Critical fixes to production releases (post-1.0.0)
**Lifecycle**:
- Branch from: Release tag (e.g., `v1.0.0`)
- Merge into: `main`
- Tag as new release: `v1.0.1`
- Delete after: Released
**Examples**:
- `hotfix/1.0.1-security-path-traversal`
- `hotfix/1.1.1-rss-encoding`
**Workflow**:
```bash
# Create hotfix from release tag
git checkout -b hotfix/1.0.1-security-fix v1.0.0
# Fix the issue
git commit -m "Fix security vulnerability"
# Update version
# Edit starpunk/__init__.py: __version__ = "1.0.1"
# Update CHANGELOG.md
git commit -m "Bump version to 1.0.1"
# Tag the hotfix
git tag -a v1.0.1 -m "Hotfix 1.0.1: Security vulnerability fix"
# Merge into main
git checkout main
git merge hotfix/1.0.1-security-fix
# Push
git push origin main v1.0.1
# Delete hotfix branch
git branch -d hotfix/1.0.1-security-fix
```
### Release Branches (Optional)
**Naming**: `release/<version>`
**Purpose**: Prepare for release (testing, docs, version bumps)
**Used when**: Release preparation requires multiple commits and testing
**Note**: For V1 (simple project), we likely don't need release branches. We can prepare releases directly on `main` or feature branches.
**If used**:
```bash
# Create release branch
git checkout -b release/1.0.0 main
# Prepare release
# - Update version numbers
# - Update CHANGELOG.md
# - Update documentation
# - Final testing
git commit -m "Prepare release 1.0.0"
# Tag
git tag -a v1.0.0 -m "Release 1.0.0: First stable release"
# Merge to main
git checkout main
git merge release/1.0.0
# Push
git push origin main v1.0.0
# Delete release branch
git branch -d release/1.0.0
```
## Branch Naming Conventions
### Format
**Preferred**: `<type>/<description>`
**Types**:
- `feature/` - New features
- `fix/` - Bug fixes
- `bugfix/` - Bug fixes (alternative)
- `hotfix/` - Production hotfixes
- `docs/` - Documentation only
- `refactor/` - Code refactoring
- `test/` - Test additions/changes
- `chore/` - Maintenance tasks
**Description**:
- Use lowercase
- Use hyphens to separate words
- Be descriptive but concise
- Reference issue number if applicable
### Examples
**Good**:
- `feature/micropub-create-action`
- `fix/rss-pubdate-timezone`
- `docs/api-documentation`
- `refactor/note-storage-layer`
- `test/slug-generation-edge-cases`
- `chore/update-dependencies`
**Acceptable** (simple description):
- `micropub-endpoint`
- `rss-feed`
- `auth-integration`
**Avoid**:
- `my-feature` (too vague)
- `feature/Feature1` (not descriptive)
- `fix_bug` (use hyphens)
- `FEATURE-MICROPUB` (use lowercase)
## Workflows
### Development Workflow (Pre-1.0)
**For single developer**:
1. Work directly on `main` for small changes
2. Use feature branches for larger features
3. Commit frequently with clear messages
4. Tag development milestones (e.g., `v0.1.0`)
**For multiple developers**:
1. Always use feature branches
2. Create pull requests
3. Review before merging
4. Delete feature branches after merge
### Feature Development
```bash
# Start feature
git checkout -b feature/new-feature main
# Develop
git add file.py
git commit -m "Implement core functionality"
# Keep updated
git fetch origin
git rebase origin/main
# Finish
git checkout main
git merge feature/new-feature
git push origin main
git branch -d feature/new-feature
```
### Release Workflow
**For development releases (0.x.y)**:
```bash
# Ensure on main
git checkout main
# Update version
# Edit starpunk/__init__.py
# Update CHANGELOG.md
# Commit
git add starpunk/__init__.py CHANGELOG.md
git commit -m "Bump version to 0.2.0"
# Tag
git tag -a v0.2.0 -m "Development release 0.2.0: Phase 1.2 complete"
# Push
git push origin main v0.2.0
```
**For stable releases (1.0.0+)**:
```bash
# Option 1: Direct on main (simple)
git checkout main
# Update version, changelog, documentation
git commit -m "Prepare release 1.0.0"
git tag -a v1.0.0 -m "Release 1.0.0: First stable release"
git push origin main v1.0.0
# Option 2: Using release branch (if needed)
git checkout -b release/1.0.0 main
# Prepare release
git commit -m "Prepare release 1.0.0"
git tag -a v1.0.0 -m "Release 1.0.0: First stable release"
git checkout main
git merge release/1.0.0
git push origin main v1.0.0
git branch -d release/1.0.0
```
### Hotfix Workflow
```bash
# Create from release tag
git checkout -b hotfix/1.0.1-critical-fix v1.0.0
# Fix
git commit -m "Fix critical bug"
# Version bump
git commit -m "Bump version to 1.0.1"
# Tag
git tag -a v1.0.1 -m "Hotfix 1.0.1: Critical bug fix"
# Merge to main
git checkout main
git merge hotfix/1.0.1-critical-fix
# Push
git push origin main v1.0.1
# Clean up
git branch -d hotfix/1.0.1-critical-fix
```
## Branch Protection Rules
### Main Branch Protection
**For solo development**:
- Recommended but not enforced via GitHub
- Self-discipline: treat `main` as protected
- Don't force push
- Don't rewrite history
**For team development**:
- Require pull request reviews
- Require status checks to pass
- Prevent force push
- Prevent deletion
**GitHub settings** (when ready):
```
Settings → Branches → Add branch protection rule
Branch name pattern: main
Protect matching branches:
☑ Require a pull request before merging
☑ Require approvals (1)
☑ Require status checks to pass before merging
☑ Require branches to be up to date before merging
☑ Require conversation resolution before merging
☑ Do not allow bypassing the above settings
☐ Allow force pushes (NEVER enable)
☐ Allow deletions (NEVER enable)
```
## Tagging Strategy
### Tag Format
**Version tags**: `vMAJOR.MINOR.PATCH[-PRERELEASE]`
**Examples**:
- `v0.1.0` - Development release
- `v1.0.0` - First stable release
- `v1.0.1` - Patch release
- `v1.1.0` - Minor release
- `v2.0.0` - Major release
- `v1.0.0-alpha.1` - Pre-release
### Tag Types
**Annotated tags** (ALWAYS use for releases):
```bash
git tag -a v1.0.0 -m "Release 1.0.0: First stable release"
```
**Why annotated**:
- Contains tagger, date, message
- Can include release notes
- Can be GPG signed
- Treated as full Git objects
- Better for releases
**Lightweight tags** (NEVER use for releases):
```bash
git tag v1.0.0 # Don't do this for releases
```
### Tag Messages
**Format**:
```
Release MAJOR.MINOR.PATCH: <Brief description>
[Optional longer description]
[Release highlights]
```
**Examples**:
```bash
git tag -a v1.0.0 -m "Release 1.0.0: First stable release
Complete IndieWeb CMS implementation with:
- IndieAuth authentication
- Micropub publishing endpoint
- RSS feed generation
- File-based note storage
- Markdown support"
git tag -a v1.0.1 -m "Hotfix 1.0.1: Security vulnerability fix"
git tag -a v0.2.0 -m "Development release 0.2.0: Phase 1.2 complete"
```
### Viewing Tags
```bash
# List all tags
git tag
# List tags with messages
git tag -n
# Show tag details
git show v1.0.0
# List tags matching pattern
git tag -l "v1.0.*"
```
### Pushing Tags
```bash
# Push specific tag
git push origin v1.0.0
# Push all tags
git push origin --tags
# Delete remote tag (if needed)
git push origin :refs/tags/v1.0.0
```
## Integration with Semantic Versioning
### Version-to-Branch Mapping
**Development phase (0.x.y)**:
- Work on `main`
- Tag development milestones: `v0.1.0`, `v0.2.0`, etc.
- Breaking changes allowed
**Stable releases (1.x.y)**:
- Work on `main` or feature branches
- Tag stable releases: `v1.0.0`, `v1.1.0`, etc.
- Breaking changes require major version bump
**Major releases (2.0.0+)**:
- Work on `main` or feature branches
- Tag major releases: `v2.0.0`, `v3.0.0`, etc.
- Document breaking changes thoroughly
### Branch-to-Release Flow
```
feature/micropub → main → v0.1.0 (development)
feature/rss → main → v0.2.0 (development)
feature/auth → main → v0.3.0 (development)
main → v1.0.0 (stable)
fix/bug → main → v1.0.1 (patch)
feature/new → main → v1.1.0 (minor)
feature/breaking → main → v2.0.0 (major)
```
## Common Scenarios
### Scenario 1: Developing a New Feature
```bash
# Create feature branch
git checkout -b feature/micropub-endpoint main
# Develop
git commit -am "Add micropub create action"
git commit -am "Add micropub update action"
# Keep updated with main
git fetch origin
git rebase origin/main
# Merge when ready
git checkout main
git merge feature/micropub-endpoint
# Push and clean up
git push origin main
git branch -d feature/micropub-endpoint
```
### Scenario 2: Releasing a Development Version
```bash
# Update version
echo '__version__ = "0.2.0"' > starpunk/__init__.py
# Update changelog
# Edit CHANGELOG.md
# Commit
git commit -am "Bump version to 0.2.0"
# Tag
git tag -a v0.2.0 -m "Development release 0.2.0"
# Push
git push origin main v0.2.0
```
### Scenario 3: First Stable Release
```bash
# Final preparations on main
git commit -am "Update documentation for 1.0.0"
# Version bump
echo '__version__ = "1.0.0"' > starpunk/__init__.py
# Edit CHANGELOG.md
git commit -am "Bump version to 1.0.0"
# Tag
git tag -a v1.0.0 -m "Release 1.0.0: First stable release"
# Push
git push origin main v1.0.0
```
### Scenario 4: Critical Production Bug
```bash
# Create hotfix from last release
git checkout -b hotfix/1.0.1-security-fix v1.0.0
# Fix the bug
git commit -am "Fix security vulnerability"
# Version bump
echo '__version__ = "1.0.1"' > starpunk/__init__.py
# Edit CHANGELOG.md
git commit -am "Bump version to 1.0.1"
# Tag
git tag -a v1.0.1 -m "Hotfix 1.0.1: Security vulnerability fix"
# Merge to main
git checkout main
git merge hotfix/1.0.1-security-fix
# Push
git push origin main v1.0.1
# Clean up
git branch -d hotfix/1.0.1-security-fix
```
### Scenario 5: Multiple Features in Progress
```bash
# Developer 1: Feature A
git checkout -b feature/feature-a main
# Work on feature A
# Developer 2: Feature B
git checkout -b feature/feature-b main
# Work on feature B
# Feature A finishes first
git checkout main
git merge feature/feature-a
git push origin main
# Feature B rebases onto updated main
git checkout feature/feature-b
git rebase origin/main
# Continue work
# Feature B finishes
git checkout main
git merge feature/feature-b
git push origin main
```
## Best Practices
### Do
1. **Commit often** with clear messages
2. **Pull before push** to avoid conflicts
3. **Rebase feature branches** to keep history clean
4. **Delete merged branches** to reduce clutter
5. **Tag releases** with annotated tags
6. **Write descriptive commit messages** (50 char summary, then details)
7. **Test before merging** to main
8. **Use pull requests** for team development
9. **Keep main stable** - always passing tests
10. **Document breaking changes** in commits and changelog
### Don't
1. **Never force push** to `main`
2. **Never rewrite history** on `main`
3. **Don't commit directly** to `main` (team development)
4. **Don't merge broken code** - tests must pass
5. **Don't create long-lived branches** - integrate frequently
6. **Don't use lightweight tags** for releases
7. **Don't forget to push tags** after creating them
8. **Don't merge without updating** from origin first
9. **Don't commit secrets** or sensitive data
10. **Don't skip version bumps** before tagging
### Commit Message Format
**Format**:
```
<type>: <summary> (50 chars or less)
<optional detailed description>
<optional footer: references, breaking changes>
```
**Types**:
- `feat:` New feature
- `fix:` Bug fix
- `docs:` Documentation
- `style:` Formatting, whitespace
- `refactor:` Code refactoring
- `test:` Adding tests
- `chore:` Maintenance tasks
**Examples**:
```
feat: Add Micropub create endpoint
Implements the create action for Micropub specification.
Supports h-entry posts with content, name, and published properties.
Refs: #15
fix: Correct RSS pubDate timezone handling
Previously used local timezone, now uses UTC as per RSS spec.
Fixes: #23
docs: Update installation instructions
chore: Bump version to 1.0.0
```
## Troubleshooting
### Problem: Merge Conflict
```bash
# During merge
git merge feature/my-feature
# CONFLICT (content): Merge conflict in file.py
# Resolve conflicts
# Edit file.py, resolve conflicts
git add file.py
git commit -m "Merge feature/my-feature"
```
### Problem: Accidentally Committed to Main
```bash
# If not pushed yet
git reset HEAD~1 # Undo last commit, keep changes
git stash # Save changes
git checkout -b feature/my-feature # Create feature branch
git stash pop # Apply changes
git commit -am "Feature implementation"
```
### Problem: Need to Update Feature Branch
```bash
# Option 1: Rebase (clean history)
git checkout feature/my-feature
git rebase origin/main
# Option 2: Merge (preserves history)
git checkout feature/my-feature
git merge origin/main
```
### Problem: Wrong Tag Name
```bash
# Delete local tag
git tag -d v1.0.0
# Delete remote tag
git push origin :refs/tags/v1.0.0
# Create correct tag
git tag -a v1.0.1 -m "Release 1.0.1"
git push origin v1.0.1
```
## References
### Internal Documentation
- [Versioning Strategy](/home/phil/Projects/starpunk/docs/standards/versioning-strategy.md) - Version numbering scheme
- [ADR-008: Versioning Strategy](/home/phil/Projects/starpunk/docs/decisions/ADR-008-versioning-strategy.md) - Versioning decision rationale
- [ADR-009: Git Branching Strategy](/home/phil/Projects/starpunk/docs/decisions/ADR-009-git-branching-strategy.md) - This strategy's decision record
- [Development Setup](/home/phil/Projects/starpunk/docs/standards/development-setup.md) - Development environment
### External Resources
- [Git Branching Model](https://nvie.com/posts/a-successful-git-branching-model/) - Git Flow (inspiration, not followed exactly)
- [GitHub Flow](https://guides.github.com/introduction/flow/) - Simpler flow (closer to our approach)
- [Semantic Versioning](https://semver.org/) - Version numbering
- [Git Documentation](https://git-scm.com/doc) - Official Git documentation
---
**Document**: Git Branching Strategy
**Version**: 1.0
**Last Updated**: 2025-11-18
**Status**: Active