725 lines
16 KiB
Markdown
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
|