Files
beads/docs/GIT_INTEGRATION.md
Steve Yegge e7fd1dd3b6 Document files created by bd init and clarify .gitattributes should be committed
Fixes #299

Added comprehensive documentation to help new users understand what files
should be committed vs ignored after running bd init:

1. README.md:
   - New "Files Created by bd init" section
   - Clear lists of files to commit vs ignore
   - Explains purpose of .gitattributes for team collaboration

2. docs/GIT_INTEGRATION.md:
   - Enhanced .gitattributes section with IMPORTANT notice
   - Explains why it must be committed (merge driver config)
   - Lists benefits of intelligent JSONL merging

Key clarification: .gitattributes should be COMMITTED (not ignored) as it
configures git merge behavior for the entire team.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 21:29:20 -05:00

535 lines
14 KiB
Markdown

# Git Integration Guide
**For:** AI agents and developers managing bd git workflows
**Version:** 0.21.0+
## Overview
bd integrates deeply with git for issue tracking synchronization. This guide covers merge conflict resolution, intelligent merge drivers, git worktrees, and protected branch workflows.
## Git Worktrees
**⚠️ Important Limitation:** Daemon mode does NOT work correctly with `git worktree`.
### The Problem
Git worktrees share the same `.git` directory and `.beads` database:
- All worktrees use the same `.beads/beads.db` file
- Daemon doesn't know which branch each worktree has checked out
- Can commit/push changes to the wrong branch
- Leads to confusion and incorrect git history
### What You Lose Without Daemon Mode
- **Auto-sync** - No automatic commit/push of changes (use `bd sync` manually)
- **MCP server** - beads-mcp requires daemon for multi-repo support
- **Background watching** - No automatic detection of remote changes
### Solutions for Worktree Users
**1. Use `--no-daemon` flag (recommended):**
```bash
bd --no-daemon ready
bd --no-daemon create "Fix bug" -p 1
bd --no-daemon update bd-42 --status in_progress
```
**2. Disable daemon via environment (entire session):**
```bash
export BEADS_NO_DAEMON=1
bd ready # All commands use direct mode
```
**3. Disable auto-start (less safe, still warns):**
```bash
export BEADS_AUTO_START_DAEMON=false
```
### Automatic Detection
bd automatically detects worktrees and shows prominent warning if daemon mode is active. The `--no-daemon` mode works correctly since it operates directly on the database without shared state.
### Why It Matters
The daemon maintains its own view of the current working directory and git state. When multiple worktrees share the same `.beads` database, the daemon may commit changes intended for one branch to a different branch.
## Handling Merge Conflicts
**With hash-based IDs (v0.20.1+), ID collisions are eliminated!** Different issues get different hash IDs, so most git merges succeed cleanly.
### When Conflicts Occur
Git conflicts in `.beads/beads.jsonl` happen when:
- **Same issue modified on both branches** (different timestamps/fields)
- This is a **same-issue update conflict**, not an ID collision
- Conflicts are rare in practice since hash IDs prevent structural collisions
### Automatic Detection
bd automatically detects conflict markers and shows clear resolution steps:
```bash
# bd import rejects files with conflict markers
bd import -i .beads/beads.jsonl
# Error: JSONL file contains git conflict markers
# Resolve with: git checkout --theirs .beads/beads.jsonl
# Validate for conflicts
bd validate --checks=conflicts
```
Conflict markers detected: `<<<<<<<`, `=======`, `>>>>>>>`
### Resolution Workflow
```bash
# After git merge creates conflict in .beads/beads.jsonl
# Option 1: Accept their version (remote)
git checkout --theirs .beads/beads.jsonl
bd import -i .beads/beads.jsonl
# Option 2: Keep our version (local)
git checkout --ours .beads/beads.jsonl
bd import -i .beads/beads.jsonl
# Option 3: Manual resolution in editor
# Edit .beads/beads.jsonl to remove conflict markers
bd import -i .beads/beads.jsonl
# Commit the merge
git add .beads/beads.jsonl
git commit
```
**Note:** `bd import` automatically handles updates - same ID with different content is a normal update operation. No special flags needed. If you accidentally modified the same issue in both branches, just pick whichever version is more complete.
## Intelligent Merge Driver (Auto-Configured)
**As of v0.21+**, bd automatically configures its own merge driver during `bd init`. This uses the beads-merge algorithm (by @neongreen, vendored into bd) to provide intelligent JSONL merging.
### What It Does
- **Field-level 3-way merging** (not line-by-line)
- **Matches issues by identity** (id + created_at + created_by)
- **Smart field merging:**
- Timestamps → max value
- Dependencies → union
- Status/priority → 3-way merge
- **Conflict markers** only for unresolvable conflicts
- **Auto-configured** during `bd init` (both interactive and `--quiet` modes)
### Auto-Configuration
**Happens automatically during `bd init`:**
```bash
# These are configured automatically:
git config merge.beads.driver "bd merge %A %O %L %R"
git config merge.beads.name "bd JSONL merge driver"
# .gitattributes entry added:
# .beads/beads.jsonl merge=beads
```
### Manual Setup
**If you skipped merge driver with `--skip-merge-driver`:**
```bash
git config merge.beads.driver "bd merge %A %O %L %R"
git config merge.beads.name "bd JSONL merge driver"
echo ".beads/beads.jsonl merge=beads" >> .gitattributes
```
### How It Works
During `git merge`, beads-merge:
1. Parses JSONL from all 3 versions (base, ours, theirs)
2. Matches issues by identity (id + created_at + created_by)
3. Merges fields intelligently per issue
4. Outputs merged JSONL or conflict markers
**Benefits:**
- Prevents spurious conflicts from line renumbering
- Handles timestamp updates gracefully
- Merges dependency/label changes intelligently
- Only conflicts on true semantic conflicts
### Alternative: Standalone beads-merge Binary
**If you prefer the standalone binary (same algorithm):**
```bash
# Install (requires Go 1.21+)
git clone https://github.com/neongreen/mono.git
cd mono/beads-merge
go install
# Configure Git merge driver
git config merge.beads.name "JSONL merge driver for beads"
git config merge.beads.driver "beads-merge %A %O %A %B"
```
### Jujutsu Integration
**For Jujutsu users**, add to `~/.jjconfig.toml`:
```toml
[merge-tools.beads-merge]
program = "beads-merge"
merge-args = ["$output", "$base", "$left", "$right"]
merge-conflict-exit-codes = [1]
```
Then resolve with:
```bash
jj resolve --tool=beads-merge
```
## Protected Branch Workflows
**If your repository uses protected branches** (GitHub, GitLab, etc.), bd can commit to a separate branch instead of `main`:
### Configuration
```bash
# Initialize with separate sync branch
bd init --branch beads-metadata
# Or configure existing setup
bd config set sync.branch beads-metadata
```
### How It Works
- Beads commits issue updates to `beads-metadata` instead of `main`
- Uses git worktrees (lightweight checkouts) in `.git/beads-worktrees/`
- Your main working directory is never affected
- Periodically merge `beads-metadata` back to `main` via pull request
### Daily Workflow (Unchanged for Agents)
```bash
# Agents work normally - no changes needed!
bd create "Fix authentication" -t bug -p 1
bd update bd-a1b2 --status in_progress
bd close bd-a1b2 "Fixed"
```
All changes automatically commit to `beads-metadata` branch (if daemon is running with `--auto-commit`).
### Merging to Main (Humans)
```bash
# Check what's changed
bd sync --status
# Option 1: Create pull request
git push origin beads-metadata
# Then create PR on GitHub/GitLab
# Option 2: Direct merge (if allowed)
bd sync --merge
```
### Benefits
- ✅ Works with protected `main` branches
- ✅ No disruption to agent workflows
- ✅ Platform-agnostic (works on any git platform)
- ✅ Backward compatible (opt-in via config)
See [PROTECTED_BRANCHES.md](PROTECTED_BRANCHES.md) for complete setup guide, troubleshooting, and examples.
## Git Hooks Integration
**STRONGLY RECOMMENDED:** Install git hooks for automatic sync and consistency.
### Installation
```bash
# One-time setup in each beads workspace
./examples/git-hooks/install.sh
```
### What Gets Installed
**pre-commit hook:**
- Flushes pending changes immediately before commit
- Bypasses 30-second debounce
- Guarantees JSONL is current
**post-merge hook:**
- Imports updated JSONL after pull/merge
- Guarantees database sync after remote changes
**pre-push hook:**
- Exports database to JSONL before push
- Prevents stale JSONL from reaching remote
- **Critical for multi-workspace consistency**
### Why Hooks Matter
**Without pre-push hook:**
- Database changes committed locally
- Stale JSONL pushed to remote
- Other workspaces diverge from truth
**With pre-push hook:**
- JSONL always reflects database state
- All workspaces stay synchronized
- No manual `bd sync` needed
See [examples/git-hooks/README.md](../examples/git-hooks/README.md) for details.
## Multi-Workspace Sync Strategies
### Centralized Repository Pattern
```
┌──────────────┐
│ Developer A │────┐
│ (Workspace) │ │
└──────────────┘ │
┌──────────────┐ ┌─────────────────┐
│ Developer B │─▶│ Central Repo │
│ (Workspace) │ │ (.beads/*.jsonl)│
└──────────────┘ └─────────────────┘
┌──────────────┐ │
│ CI/CD │────┘
│ (Workspace) │
└──────────────┘
```
**Best for:**
- Teams working on shared repository
- CI/CD integration
- Multi-agent workflows
**Key points:**
- Each workspace has its own daemon
- Git is the source of truth
- Auto-sync keeps workspaces consistent
### Fork-Based Pattern
```
┌──────────────┐ ┌─────────────────┐
│ OSS Contrib │─────▶│ Planning Repo │
│ (Fork) │ │ (.beads/*.jsonl)│
└──────────────┘ └─────────────────┘
│ PR
┌─────────────────┐
│ Upstream Repo │
│ (no .beads/) │
└─────────────────┘
```
**Best for:**
- Open source contributors
- Solo developers
- Private task tracking on public repos
**Setup:**
```bash
bd init --contributor # Interactive wizard
```
See [MULTI_REPO_MIGRATION.md](MULTI_REPO_MIGRATION.md) for complete guide.
### Team Branch Pattern
```
┌──────────────┐
│ Team Member │────┐
│ (main) │ │
└──────────────┘ │
┌──────────────┐ ┌─────────────────┐
│ Team Member │─▶│ Shared Repo │
│ (main) │ │ (beads-metadata)│
└──────────────┘ └─────────────────┘
```
**Best for:**
- Teams on protected branches
- Managed git workflows
- Review-before-merge policies
**Setup:**
```bash
bd init --team # Interactive wizard
```
See [MULTI_REPO_MIGRATION.md](MULTI_REPO_MIGRATION.md) for complete guide.
## Sync Timing and Control
### Automatic Sync (Default)
**With daemon running:**
- Export to JSONL: 30-second debounce after changes
- Import from JSONL: when file is newer than DB
- Commit/push: configurable via `--auto-commit` / `--auto-push`
**30-second debounce provides transaction window:**
- Multiple changes within 30s get batched
- Single JSONL export/commit for the batch
- Prevents commit spam
### Manual Sync
```bash
# Force immediate sync (bypass debounce)
bd sync
# What it does:
# 1. Export pending changes to JSONL
# 2. Commit to git
# 3. Pull from remote
# 4. Import any updates
# 5. Push to remote
```
**ALWAYS run `bd sync` at end of agent sessions** to ensure changes are committed/pushed.
### Disable Automatic Sync
```bash
# Disable auto-flush (no export until manual sync)
bd --no-auto-flush ready
# Disable auto-import (no import on file changes)
bd --no-auto-import ready
# Disable both (manual sync only)
export BEADS_NO_DAEMON=1 # Direct mode
```
## Git Configuration Best Practices
### Recommended .gitignore
```
# bd database (not tracked - JSONL is source of truth)
.beads/beads.db
.beads/beads.db-*
.beads/bd.sock
.beads/bd.pipe
# bd daemon state
.beads/.exclusive-lock
# Git worktrees (if using protected branches)
.git/beads-worktrees/
```
### Recommended .gitattributes
**IMPORTANT:** The `.gitattributes` file should be **committed to git**, not ignored. It configures merge behavior for the entire team.
```
# Intelligent merge driver for JSONL (auto-configured by bd init)
.beads/beads.jsonl merge=beads
# Treat JSONL as text for diffs
.beads/*.jsonl text diff
```
This file is automatically created by `bd init` and is essential for:
- Preventing spurious merge conflicts in `.beads/beads.jsonl`
- Enabling field-level 3-way merging instead of line-by-line
- Ensuring all team members get intelligent JSONL merging
### Git LFS Considerations
**Do NOT use Git LFS for `.beads/beads.jsonl`:**
- JSONL needs intelligent merge (doesn't work with LFS)
- File size stays reasonable (<1MB per 10K issues)
- Text diffs are valuable for review
## Troubleshooting Git Issues
### Issue: "JSONL file is ahead of database"
**Symptoms:**
```
WARN Database timestamp older than JSONL, importing...
```
**Solutions:**
```bash
# Normal after git pull - auto-import handles it
# If stuck, force import:
bd import -i .beads/beads.jsonl
```
### Issue: "Database is ahead of JSONL"
**Symptoms:**
```
WARN JSONL timestamp older than database, exporting...
```
**Solutions:**
```bash
# Normal after local changes - auto-export handles it
# If stuck, force export:
bd sync
```
### Issue: Merge conflicts every time
**Symptoms:**
- Git merge always creates conflicts in `.beads/beads.jsonl`
- Merge driver not being used
**Solutions:**
```bash
# Check merge driver configured
git config merge.beads.driver
# Reinstall if missing
bd init --skip-db # Only reconfigure git, don't touch database
# Verify .gitattributes
grep "beads.jsonl" .gitattributes
# Expected: .beads/beads.jsonl merge=beads
```
### Issue: Changes not syncing to other workspaces
**Symptoms:**
- Agent A creates issue
- Agent B doesn't see it after `git pull`
**Solutions:**
```bash
# Agent A: Ensure changes were pushed
bd sync
git push
# Agent B: Force import
git pull
bd import -i .beads/beads.jsonl
# Check git hooks installed (prevent future issues)
./examples/git-hooks/install.sh
```
## See Also
- [AGENTS.md](../AGENTS.md) - Main agent workflow guide
- [DAEMON.md](DAEMON.md) - Daemon management and configuration
- [PROTECTED_BRANCHES.md](PROTECTED_BRANCHES.md) - Protected branch workflows
- [MULTI_REPO_MIGRATION.md](MULTI_REPO_MIGRATION.md) - Multi-repo patterns
- [examples/git-hooks/README.md](../examples/git-hooks/README.md) - Git hooks integration