Files
beads/docs/PROTECTED_BRANCHES.md
Steve Yegge edf1f71fa7 Add comprehensive protected branch workflow documentation (bd-5ce8)
Created complete documentation suite for using beads with protected branches:

1. **docs/PROTECTED_BRANCHES.md** - Comprehensive 600+ line guide covering:
   - Quick start and setup
   - How git worktrees work
   - Daily workflow for agents and humans
   - Merging strategies (PR and direct)
   - Troubleshooting common issues
   - Platform-specific notes (GitHub, GitLab, Bitbucket)
   - Advanced topics (CI/CD, multi-clone sync, etc.)

2. **AGENTS.md** - Added "Protected Branch Workflow" section:
   - Quick reference for agents
   - No changes needed to agent workflows
   - Commands for setup and merging
   - Link to detailed docs

3. **README.md** - Updated with:
   - Protected branch support feature flag
   - Quick start instructions with --branch flag
   - Link to comprehensive guide

4. **examples/protected-branch/** - Working example with:
   - Step-by-step demo
   - Multi-clone sync workflow
   - GitHub Actions integration example
   - Directory structure explanation
   - Troubleshooting tips

All commands verified:
- bd init --branch <name>
- bd config get/set sync.branch
- bd sync --status
- bd sync --merge

Documentation is platform-agnostic and works with GitHub, GitLab,
Bitbucket, or any git platform with branch protection.

Closes bd-5ce8

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 18:41:51 -08:00

659 lines
16 KiB
Markdown

# Protected Branch Workflow
This guide explains how to use beads with protected branches on platforms like GitHub, GitLab, and Bitbucket.
## Table of Contents
- [Overview](#overview)
- [Quick Start](#quick-start)
- [How It Works](#how-it-works)
- [Setup](#setup)
- [Daily Workflow](#daily-workflow)
- [Merging Changes](#merging-changes)
- [Troubleshooting](#troubleshooting)
- [FAQ](#faq)
## Overview
**Problem:** GitHub and other platforms let you protect branches (like `main`) to require pull requests for all changes. This prevents beads from auto-committing issue updates directly to `main`.
**Solution:** Beads can commit to a separate branch (like `beads-metadata`) using git worktrees, while keeping your main working directory untouched. Periodically merge the metadata branch back to `main` via a pull request.
**Benefits:**
- ✅ Works with any git platform's branch protection
- ✅ Main branch stays protected
- ✅ No disruption to your primary working directory
- ✅ Backward compatible (opt-in via config)
- ✅ Minimal disk overhead (uses sparse checkout)
- ✅ Platform-agnostic solution
## Quick Start
**1. Initialize beads with a separate sync branch:**
```bash
cd your-project
bd init --branch beads-metadata
```
This creates a `.beads/` directory and configures beads to commit to `beads-metadata` instead of `main`.
**2. Start the daemon with auto-commit:**
```bash
bd daemon start --auto-commit
```
The daemon will automatically commit issue changes to the `beads-metadata` branch.
**3. When ready, merge to main:**
```bash
# Check what's changed
bd sync --status
# Merge to main (creates a pull request or direct merge)
bd sync --merge
```
That's it! The complete workflow is described below.
## How It Works
### Git Worktrees
Beads uses [git worktrees](https://git-scm.com/docs/git-worktree) to maintain a lightweight checkout of your sync branch. Think of it as a mini git clone that shares the same repository history.
**Directory structure:**
```
your-project/
├── .git/ # Main git directory
│ └── beads-worktrees/
│ └── beads-metadata/ # Worktree (only .beads/ checked out)
│ └── .beads/
│ └── beads.jsonl
├── .beads/ # Your main copy
│ ├── beads.db
│ └── beads.jsonl
└── src/ # Your code (untouched)
```
**Key points:**
- The worktree is in `.git/beads-worktrees/` (hidden from your workspace)
- Only `.beads/` is checked out in the worktree (sparse checkout)
- Changes to issues are committed in the worktree
- Your main working directory is never affected
- Disk overhead is minimal (~few MB for the worktree)
### Automatic Sync
When you update an issue:
1. Issue is updated in `.beads/beads.db` (SQLite database)
2. Daemon exports to `.beads/beads.jsonl` (JSONL file)
3. JSONL is copied to worktree (`.git/beads-worktrees/beads-metadata/.beads/`)
4. Daemon commits the change in the worktree to `beads-metadata` branch
5. Main branch stays untouched (no commits on `main`)
## Setup
### Option 1: Initialize New Project
```bash
cd your-project
bd init --branch beads-metadata
```
This will:
- Create `.beads/` directory with database
- Set `sync.branch` config to `beads-metadata`
- Import any existing issues from git (if present)
- Prompt to install git hooks (recommended: say yes)
### Option 2: Migrate Existing Project
If you already have beads set up and want to switch to a separate branch:
```bash
# Set the sync branch
bd config set sync.branch beads-metadata
# Start the daemon (it will create the worktree automatically)
bd daemon start --auto-commit
```
### Daemon Configuration
For automatic commits to the sync branch:
```bash
# Start daemon with auto-commit
bd daemon start --auto-commit
# Or with auto-commit and auto-push
bd daemon start --auto-commit --auto-push
```
**Daemon modes:**
- `--auto-commit`: Commits to sync branch after each change
- `--auto-push`: Also pushes to remote after each commit
- Default interval: 5 seconds (check for changes every 5s)
**Recommended:** Use `--auto-commit` but not `--auto-push` if you want to review changes before pushing. Use `--auto-push` if you want fully hands-free sync.
### Environment Variables
You can also configure the sync branch via environment variable:
```bash
export BEADS_SYNC_BRANCH=beads-metadata
bd daemon start --auto-commit
```
This is useful for CI/CD or temporary overrides.
## Daily Workflow
### For AI Agents
AI agents work exactly the same way as before:
```bash
# Create issues
bd create "Implement user authentication" -t feature -p 1
# Update issues
bd update bd-a1b2 --status in_progress
# Close issues
bd close bd-a1b2 "Completed authentication"
```
All changes are automatically committed to the `beads-metadata` branch by the daemon. No changes are needed to agent workflows!
### For Humans
**Check status:**
```bash
# See what's changed on the sync branch
bd sync --status
```
This shows the diff between `beads-metadata` and `main` (or your current branch).
**Manual commit (if not using daemon):**
```bash
bd sync --flush-only # Export to JSONL and commit to sync branch
```
**Pull changes from remote:**
```bash
# Pull updates from other collaborators
bd sync --no-push
```
This pulls changes from the remote sync branch and imports them to your local database.
## Merging Changes
### Option 1: Via Pull Request (Recommended)
For protected branches with required reviews:
```bash
# 1. Push your sync branch
git push origin beads-metadata
# 2. Create PR on GitHub/GitLab/etc.
# - Base: main
# - Compare: beads-metadata
# 3. After PR is merged, update your local main
git checkout main
git pull
bd import # Import the merged changes
```
### Option 2: Direct Merge (If Allowed)
If you have push access to `main`:
```bash
# Check what will be merged
bd sync --merge --dry-run
# Merge sync branch to main
bd sync --merge
# This will:
# - Switch to main branch
# - Merge beads-metadata with --no-ff (creates merge commit)
# - Push to remote
# - Import merged changes to database
```
**Safety checks:**
- ✅ Verifies you're not on the sync branch
- ✅ Checks for uncommitted changes in working tree
- ✅ Detects merge conflicts and provides resolution steps
- ✅ Uses `--no-ff` for clear history
### Merge Conflicts
If you encounter conflicts during merge:
```bash
# bd sync --merge will detect conflicts and show:
Error: Merge conflicts detected
Conflicting files:
.beads/beads.jsonl
To resolve:
1. Fix conflicts in .beads/beads.jsonl
2. git add .beads/beads.jsonl
3. git commit
4. bd import # Reimport to sync database
```
**Resolving JSONL conflicts:**
JSONL files are append-only and line-based, so conflicts are rare. When they occur:
1. Open `.beads/beads.jsonl` and look for conflict markers (`<<<<<<<`, `=======`, `>>>>>>>`)
2. Both versions are usually valid - keep both lines
3. Remove the conflict markers
4. Save and commit
Example conflict resolution:
```jsonl
<<<<<<< HEAD
{"id":"bd-a1b2","title":"Feature A","status":"closed","updated_at":"2025-11-02T10:00:00Z"}
=======
{"id":"bd-a1b2","title":"Feature A","status":"in_progress","updated_at":"2025-11-02T09:00:00Z"}
>>>>>>> beads-metadata
```
**Resolution:** Keep the line with the newer `updated_at`:
```jsonl
{"id":"bd-a1b2","title":"Feature A","status":"closed","updated_at":"2025-11-02T10:00:00Z"}
```
Then:
```bash
git add .beads/beads.jsonl
git commit -m "Resolve beads.jsonl merge conflict"
bd import # Import to database (will use latest timestamp)
```
## Troubleshooting
### "fatal: refusing to merge unrelated histories"
This happens if you created the sync branch independently. Merge with `--allow-unrelated-histories`:
```bash
git merge beads-metadata --allow-unrelated-histories --no-ff
```
Or use `bd sync --merge` which handles this automatically.
### "worktree already exists"
If the worktree is corrupted or in a bad state:
```bash
# Remove the worktree
rm -rf .git/beads-worktrees/beads-metadata
# Prune stale worktree entries
git worktree prune
# Restart daemon (it will recreate the worktree)
bd daemon restart
```
### "branch 'beads-metadata' not found"
The sync branch doesn't exist yet. The daemon will create it on the first commit. If you want to create it manually:
```bash
git checkout -b beads-metadata
git checkout main # Switch back
```
Or just let the daemon create it automatically.
### "Cannot push to protected branch"
If the sync branch itself is protected:
1. **Option 1:** Unprotect the sync branch (it's metadata, doesn't need protection)
2. **Option 2:** Use `--auto-commit` without `--auto-push`, and push manually when ready
3. **Option 3:** Use a different branch name that's not protected
### Daemon won't start
Check daemon status and logs:
```bash
# Check status
bd daemon status
# View logs
tail -f ~/.beads/daemon.log
# Restart daemon
bd daemon restart
```
Common issues:
- Port already in use: Another daemon is running
- Permission denied: Check `.beads/` directory permissions
- Git errors: Ensure git is installed and repository is initialized
### Changes not syncing between clones
Ensure all clones are configured the same way:
```bash
# On each clone, verify:
bd config get sync.branch # Should be the same (e.g., beads-metadata)
# Pull latest changes
bd sync --no-push
# Check daemon is running
bd daemon status
```
## FAQ
### Do I need to configure anything on GitHub/GitLab?
No! This is a pure git solution that works on any platform. Just protect your `main` branch as usual.
### Can I use a different branch name?
Yes! Use any branch name you want:
```bash
bd init --branch my-custom-branch
# or
bd config set sync.branch my-custom-branch
```
### Can I change the branch name later?
Yes:
```bash
bd config set sync.branch new-branch-name
bd daemon restart
```
The old worktree will remain (no harm), and a new worktree will be created for the new branch.
### What if I want to go back to committing to main?
Unset the sync branch config:
```bash
bd config set sync.branch ""
bd daemon restart
```
Beads will go back to committing directly to your current branch.
### Does this work with multiple collaborators?
Yes! Each collaborator configures their own sync branch:
```bash
# All collaborators use the same branch
bd config set sync.branch beads-metadata
```
Everyone's changes sync via the `beads-metadata` branch. Periodically merge to `main` via PR.
### How often should I merge to main?
This depends on your workflow:
- **Daily:** If you want issue history in `main` frequently
- **Per sprint:** If you batch metadata updates
- **As needed:** Only when you need others to see issue updates
There's no "right" answer - choose what fits your team.
### Can I review changes before merging?
Yes! Use `bd sync --status` to see what's changed:
```bash
bd sync --status
# Shows diff between beads-metadata and main
```
Or create a pull request and review on GitHub/GitLab.
### What about disk space?
Worktrees are very lightweight:
- Sparse checkout means only `.beads/` is checked out
- Typically < 1 MB for the worktree
- Shared git history (no duplication)
### Can I delete the worktree?
Yes, but the daemon will recreate it. If you want to clean up permanently:
```bash
# Stop daemon
bd daemon stop
# Remove worktree
git worktree remove .git/beads-worktrees/beads-metadata
# Unset sync branch
bd config set sync.branch ""
```
### Does this work with `bd sync`?
Yes! `bd sync` works normally and includes special commands for the merge workflow:
- `bd sync --status` - Show diff between branches
- `bd sync --merge` - Merge sync branch to main
- `bd sync --merge --dry-run` - Preview merge
### Can AI agents merge automatically?
Not recommended! Merging to `main` is a deliberate action that should be human-reviewed, especially with protected branches. Agents should create issues and update them; humans should merge to `main`.
However, if you want fully automated sync:
```bash
# WARNING: This bypasses branch protection!
bd daemon start --auto-commit --auto-push
bd sync --merge # Run periodically (e.g., via cron)
```
### What if I forget to merge for a long time?
No problem! The sync branch accumulates all changes. When you eventually merge:
```bash
bd sync --merge
```
All accumulated changes will be merged at once. Git history will show the full timeline.
### Can I use this with GitHub Actions or CI/CD?
Yes! Example GitHub Actions workflow:
```yaml
name: Sync Beads Metadata
on:
schedule:
- cron: '0 0 * * *' # Daily at midnight
workflow_dispatch: # Manual trigger
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0 # Full history
- name: Install bd
run: |
curl -fsSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash
- name: Pull changes
run: |
git fetch origin beads-metadata
bd sync --no-push
- name: Merge to main (if changes)
run: |
if bd sync --status | grep -q 'ahead'; then
bd sync --merge
git push origin main
fi
```
**Note:** Make sure the GitHub Action has write permissions to push to `main`.
## Platform-Specific Notes
### GitHub
Protected branch settings:
1. Go to Settings → Branches → Add rule
2. Branch name pattern: `main`
3. Check "Require pull request before merging"
4. Save
Create sync branch PR:
```bash
git push origin beads-metadata
gh pr create --base main --head beads-metadata --title "Update beads metadata"
```
### GitLab
Protected branch settings:
1. Settings → Repository → Protected Branches
2. Branch: `main`
3. Allowed to merge: Maintainers
4. Allowed to push: No one
Create sync branch MR:
```bash
git push origin beads-metadata
glab mr create --source-branch beads-metadata --target-branch main
```
### Bitbucket
Protected branch settings:
1. Repository settings → Branch permissions
2. Branch: `main`
3. Check "Prevent direct pushes"
Create sync branch PR:
```bash
git push origin beads-metadata
# Create PR via Bitbucket web UI
```
## Advanced Topics
### Multiple Sync Branches
You can use different sync branches for different purposes:
```bash
# Development branch
bd config set sync.branch beads-dev
# Production branch
bd config set sync.branch beads-prod
```
Switch between them as needed.
### Syncing with Upstream
If you're working on a fork:
```bash
# Add upstream
git remote add upstream https://github.com/original/repo.git
# Fetch upstream changes
git fetch upstream
# Merge upstream beads-metadata to yours
git checkout beads-metadata
git merge upstream/beads-metadata
bd import # Import merged changes
```
### Custom Worktree Location
By default, worktrees are in `.git/beads-worktrees/`. This is hidden and automatic. If you need a custom location, you'll need to manage worktrees manually (not recommended).
## Migration Guide
### From Direct Commits to Sync Branch
If you have an existing beads setup committing to `main`:
1. **Set sync branch:**
```bash
bd config set sync.branch beads-metadata
```
2. **Restart daemon:**
```bash
bd daemon restart
```
3. **Verify:**
```bash
bd config get sync.branch # Should show: beads-metadata
```
Future commits will go to `beads-metadata`. Historical commits on `main` are preserved.
### From Sync Branch to Direct Commits
If you want to stop using a sync branch:
1. **Unset sync branch:**
```bash
bd config set sync.branch ""
```
2. **Restart daemon:**
```bash
bd daemon restart
```
Future commits will go to your current branch (e.g., `main`).
---
**Need help?** Open an issue at https://github.com/steveyegge/beads/issues