fix(gitignore): switch to whitelist approach for .beads/.gitignore (#473)
The .beads/.gitignore now ignores everything by default and explicitly whitelists tracked files. This fixes confusion about which files to commit when using protected branches workflow. Changes: - Use `*` to ignore all by default, then `!file` to whitelist - Fix config.json -> config.yaml (wrong filename in negation) - Update doctor check to validate new patterns - Update PROTECTED_BRANCHES.md documentation - Simplify git add instructions to just `git add .beads/` Fixes #473 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
43
.beads/.gitignore
vendored
43
.beads/.gitignore
vendored
@@ -1,33 +1,20 @@
|
|||||||
# SQLite databases
|
# Ignore all .beads/ contents by default (local workspace files)
|
||||||
*.db
|
# Only files explicitly whitelisted below will be tracked in git
|
||||||
*.db?*
|
*
|
||||||
*.db-journal
|
|
||||||
*.db-wal
|
|
||||||
*.db-shm
|
|
||||||
|
|
||||||
# Daemon runtime files
|
# === Files tracked in git (shared across clones) ===
|
||||||
daemon.lock
|
|
||||||
daemon.log
|
|
||||||
daemon.pid
|
|
||||||
bd.sock
|
|
||||||
|
|
||||||
# Local version tracking (prevents upgrade notification spam after git operations)
|
# This gitignore file itself
|
||||||
# bd-tok: Store version locally instead of in tracked metadata.json
|
!.gitignore
|
||||||
.local_version
|
|
||||||
|
|
||||||
# Legacy database files
|
# Issue data in JSONL format (the main data file)
|
||||||
db.sqlite
|
|
||||||
bd.db
|
|
||||||
|
|
||||||
# Merge artifacts (temporary files from 3-way merge)
|
|
||||||
beads.base.jsonl
|
|
||||||
beads.base.meta.json
|
|
||||||
beads.left.jsonl
|
|
||||||
beads.left.meta.json
|
|
||||||
beads.right.jsonl
|
|
||||||
beads.right.meta.json
|
|
||||||
|
|
||||||
# Keep JSONL exports and config (source of truth for git)
|
|
||||||
!issues.jsonl
|
!issues.jsonl
|
||||||
|
|
||||||
|
# Repository metadata (database name, JSONL filename)
|
||||||
!metadata.json
|
!metadata.json
|
||||||
!config.json
|
|
||||||
|
# Configuration template (sync branch, integrations)
|
||||||
|
!config.yaml
|
||||||
|
|
||||||
|
# Documentation for contributors
|
||||||
|
!README.md
|
||||||
|
|||||||
@@ -7,52 +7,38 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// GitignoreTemplate is the canonical .beads/.gitignore content
|
// GitignoreTemplate is the canonical .beads/.gitignore content
|
||||||
const GitignoreTemplate = `# SQLite databases
|
// Uses whitelist approach: ignore everything by default, explicitly allow tracked files.
|
||||||
*.db
|
// This prevents confusion about which files to commit (fixes GitHub #473).
|
||||||
*.db?*
|
const GitignoreTemplate = `# Ignore all .beads/ contents by default (local workspace files)
|
||||||
*.db-journal
|
# Only files explicitly whitelisted below will be tracked in git
|
||||||
*.db-wal
|
*
|
||||||
*.db-shm
|
|
||||||
|
|
||||||
# Daemon runtime files
|
# === Files tracked in git (shared across clones) ===
|
||||||
daemon.lock
|
|
||||||
daemon.log
|
|
||||||
daemon.pid
|
|
||||||
bd.sock
|
|
||||||
|
|
||||||
# Local version tracking (prevents upgrade notification spam after git ops)
|
# This gitignore file itself
|
||||||
.local_version
|
!.gitignore
|
||||||
|
|
||||||
# Legacy database files
|
# Issue data in JSONL format (the main data file)
|
||||||
db.sqlite
|
|
||||||
bd.db
|
|
||||||
|
|
||||||
# Merge artifacts (temporary files from 3-way merge)
|
|
||||||
beads.base.jsonl
|
|
||||||
beads.base.meta.json
|
|
||||||
beads.left.jsonl
|
|
||||||
beads.left.meta.json
|
|
||||||
beads.right.jsonl
|
|
||||||
beads.right.meta.json
|
|
||||||
|
|
||||||
# Backup directories created by bd reset --backup
|
|
||||||
.beads-backup-*/
|
|
||||||
|
|
||||||
# Keep JSONL exports and config (source of truth for git)
|
|
||||||
!issues.jsonl
|
!issues.jsonl
|
||||||
|
|
||||||
|
# Repository metadata (database name, JSONL filename)
|
||||||
!metadata.json
|
!metadata.json
|
||||||
!config.json
|
|
||||||
|
# Configuration template (sync branch, integrations)
|
||||||
|
!config.yaml
|
||||||
|
|
||||||
|
# Documentation for contributors
|
||||||
|
!README.md
|
||||||
`
|
`
|
||||||
|
|
||||||
// requiredPatterns are patterns that MUST be in .beads/.gitignore
|
// requiredPatterns are patterns that MUST be in .beads/.gitignore
|
||||||
|
// With the whitelist approach, we check for the blanket ignore and whitelisted files
|
||||||
var requiredPatterns = []string{
|
var requiredPatterns = []string{
|
||||||
"beads.base.jsonl",
|
"*", // Blanket ignore (whitelist approach)
|
||||||
"beads.left.jsonl",
|
"!.gitignore", // Whitelist the gitignore itself
|
||||||
"beads.right.jsonl",
|
"!issues.jsonl",
|
||||||
"beads.base.meta.json",
|
"!metadata.json",
|
||||||
"beads.left.meta.json",
|
"!config.yaml", // Fixed: was incorrectly !config.json before #473
|
||||||
"beads.right.meta.json",
|
|
||||||
"*.db?*",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckGitignore checks if .beads/.gitignore is up to date
|
// CheckGitignore checks if .beads/.gitignore is up to date
|
||||||
@@ -83,7 +69,7 @@ func CheckGitignore() DoctorCheck {
|
|||||||
return DoctorCheck{
|
return DoctorCheck{
|
||||||
Name: "Gitignore",
|
Name: "Gitignore",
|
||||||
Status: "warning",
|
Status: "warning",
|
||||||
Message: "Outdated .beads/.gitignore (missing merge artifact patterns)",
|
Message: "Outdated .beads/.gitignore (needs whitelist patterns)",
|
||||||
Detail: "Missing: " + strings.Join(missing, ", "),
|
Detail: "Missing: " + strings.Join(missing, ", "),
|
||||||
Fix: "Run: bd doctor --fix or bd init (safe to re-run)",
|
Fix: "Run: bd doctor --fix or bd init (safe to re-run)",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,21 +115,15 @@ func TestInitCommand(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(".gitignore file was not created: %v", err)
|
t.Errorf(".gitignore file was not created: %v", err)
|
||||||
} else {
|
} else {
|
||||||
// Check for essential patterns
|
// Check for essential patterns (whitelist approach - GitHub #473)
|
||||||
gitignoreStr := string(gitignoreContent)
|
gitignoreStr := string(gitignoreContent)
|
||||||
expectedPatterns := []string{
|
expectedPatterns := []string{
|
||||||
"*.db",
|
"*", // Blanket ignore
|
||||||
"*.db?*",
|
"!.gitignore", // Whitelist gitignore itself
|
||||||
"*.db-journal",
|
"!issues.jsonl", // Whitelist JSONL
|
||||||
"*.db-wal",
|
"!metadata.json",
|
||||||
"*.db-shm",
|
"!config.yaml",
|
||||||
"daemon.log",
|
"!README.md",
|
||||||
"daemon.pid",
|
|
||||||
"bd.sock",
|
|
||||||
"beads.base.jsonl",
|
|
||||||
"beads.left.jsonl",
|
|
||||||
"beads.right.jsonl",
|
|
||||||
"!issues.jsonl",
|
|
||||||
}
|
}
|
||||||
for _, pattern := range expectedPatterns {
|
for _, pattern := range expectedPatterns {
|
||||||
if !strings.Contains(gitignoreStr, pattern) {
|
if !strings.Contains(gitignoreStr, pattern) {
|
||||||
|
|||||||
@@ -38,33 +38,32 @@ bd init --branch beads-metadata
|
|||||||
|
|
||||||
This creates a `.beads/` directory and configures beads to commit to `beads-metadata` instead of `main`.
|
This creates a `.beads/` directory and configures beads to commit to `beads-metadata` instead of `main`.
|
||||||
|
|
||||||
**Important:** After initialization, you'll see some untracked files that should be committed to your protected branch:
|
**Important:** After initialization, commit the beads configuration to your protected branch:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Check what files were created
|
# The .beads/.gitignore uses a whitelist - only tracked files show up
|
||||||
git status
|
git add .beads/ .gitattributes
|
||||||
|
|
||||||
# Commit the beads configuration to your protected branch
|
|
||||||
git add .beads/.gitignore .gitattributes
|
|
||||||
git commit -m "Initialize beads issue tracker"
|
git commit -m "Initialize beads issue tracker"
|
||||||
git push origin main # Or create a PR if required
|
git push origin main # Or create a PR if required
|
||||||
```
|
```
|
||||||
|
|
||||||
**Files created by `bd init --branch`:**
|
**Files created by `bd init --branch`:**
|
||||||
|
|
||||||
Files that should be committed to your protected branch (main):
|
Files committed to your **protected branch** (main):
|
||||||
- `.beads/.gitignore` - Tells git what to ignore in .beads/ directory
|
- `.beads/.gitignore` - Whitelist of tracked files (everything else ignored)
|
||||||
- `.gitattributes` - Configures merge driver for intelligent JSONL conflict resolution
|
- `.gitattributes` - Configures merge driver for intelligent JSONL conflict resolution
|
||||||
|
|
||||||
Files that are automatically gitignored (do NOT commit):
|
Files committed to your **sync branch** (beads-metadata) by the daemon:
|
||||||
- `.beads/beads.db` - SQLite database (local only, regenerated from JSONL)
|
- `.beads/issues.jsonl` - Issue data in JSONL format
|
||||||
- `.beads/daemon.lock`, `daemon.log`, `daemon.pid` - Runtime files
|
|
||||||
- `.beads/beads.left.jsonl`, `beads.right.jsonl` - Temporary merge artifacts
|
|
||||||
|
|
||||||
The sync branch (beads-metadata) will contain:
|
|
||||||
- `.beads/beads.jsonl` - Issue data in JSONL format (committed automatically by daemon)
|
|
||||||
- `.beads/metadata.json` - Metadata about the beads installation
|
- `.beads/metadata.json` - Metadata about the beads installation
|
||||||
- `.beads/config.yaml` - Configuration template (optional)
|
- `.beads/config.yaml` - Configuration settings
|
||||||
|
- `.beads/README.md` - Documentation for contributors
|
||||||
|
|
||||||
|
Files that are **automatically ignored** (local only, never committed):
|
||||||
|
- `.beads/beads.db` - SQLite database (regenerated from JSONL)
|
||||||
|
- `.beads/daemon.*` - Runtime files (lock, log, pid, socket)
|
||||||
|
- `.beads/beads.*.jsonl` - Temporary merge artifacts
|
||||||
|
- Everything else in `.beads/` not explicitly whitelisted
|
||||||
|
|
||||||
**2. Start the daemon with auto-commit:**
|
**2. Start the daemon with auto-commit:**
|
||||||
|
|
||||||
@@ -112,17 +111,19 @@ your-project/
|
|||||||
**What lives in each branch:**
|
**What lives in each branch:**
|
||||||
|
|
||||||
Main branch (protected):
|
Main branch (protected):
|
||||||
- `.beads/.gitignore` - Tells git what to ignore
|
- `.beads/.gitignore` - Whitelist of tracked files
|
||||||
- `.gitattributes` - Merge driver configuration
|
- `.gitattributes` - Merge driver configuration
|
||||||
|
|
||||||
Sync branch (beads-metadata):
|
Sync branch (beads-metadata):
|
||||||
- `.beads/beads.jsonl` - Issue data (committed by daemon)
|
- `.beads/issues.jsonl` - Issue data (committed by daemon)
|
||||||
- `.beads/metadata.json` - Repository metadata
|
- `.beads/metadata.json` - Repository metadata
|
||||||
- `.beads/config.yaml` - Configuration template
|
- `.beads/config.yaml` - Configuration settings
|
||||||
|
- `.beads/README.md` - Documentation
|
||||||
|
|
||||||
Not tracked (gitignored):
|
Not tracked (gitignored via whitelist):
|
||||||
- `.beads/beads.db` - SQLite database (local only)
|
- `.beads/beads.db` - SQLite database (local only)
|
||||||
- `.beads/daemon.*` - Runtime files
|
- `.beads/daemon.*` - Runtime files
|
||||||
|
- Everything else not in the whitelist
|
||||||
|
|
||||||
**Key points:**
|
**Key points:**
|
||||||
- The worktree is in `.git/beads-worktrees/` (hidden from your workspace)
|
- The worktree is in `.git/beads-worktrees/` (hidden from your workspace)
|
||||||
|
|||||||
Reference in New Issue
Block a user