Files
beads/cmd/bd/branch.go
quartz 94581ab233 feat(storage): add VersionedStorage interface with history/diff/branch operations
Extends Storage interface with Dolt-specific version control capabilities:

- New VersionedStorage interface in storage/versioned.go with:
  - History queries: History(), AsOf(), Diff()
  - Branch operations: Branch(), Merge(), CurrentBranch(), ListBranches()
  - Commit operations: Commit(), GetCurrentCommit()
  - Conflict resolution: GetConflicts(), ResolveConflicts()
  - Helper types: HistoryEntry, DiffEntry, Conflict

- DoltStore implements VersionedStorage interface

- New CLI commands:
  - bd history <id> - Show issue version history
  - bd diff <from> <to> - Show changes between commits/branches
  - bd branch [name] - List or create branches
  - bd vc merge <branch> - Merge branch to current
  - bd vc commit -m <msg> - Create a commit
  - bd vc status - Show current branch/commit

- Added --as-of flag to bd show for time-travel queries

- IsVersioned() helper for graceful SQLite backend detection

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 01:55:16 -08:00

86 lines
2.0 KiB
Go

package main
import (
"fmt"
"github.com/spf13/cobra"
"github.com/steveyegge/beads/internal/storage"
"github.com/steveyegge/beads/internal/ui"
)
var branchCmd = &cobra.Command{
Use: "branch [name]",
GroupID: "sync",
Short: "List or create branches (requires Dolt backend)",
Long: `List all branches or create a new branch.
This command requires the Dolt storage backend. Without arguments,
it lists all branches. With an argument, it creates a new branch.
Examples:
bd branch # List all branches
bd branch feature-xyz # Create a new branch named feature-xyz`,
Args: cobra.MaximumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
ctx := rootCtx
// Check if storage supports versioning
vs, ok := storage.AsVersioned(store)
if !ok {
FatalErrorRespectJSON("branch requires Dolt backend (current backend does not support versioning)")
}
// If no args, list branches
if len(args) == 0 {
branches, err := vs.ListBranches(ctx)
if err != nil {
FatalErrorRespectJSON("failed to list branches: %v", err)
}
currentBranch, err := vs.CurrentBranch(ctx)
if err != nil {
// Non-fatal, just don't show current marker
currentBranch = ""
}
if jsonOutput {
outputJSON(map[string]interface{}{
"current": currentBranch,
"branches": branches,
})
return
}
fmt.Printf("\n%s Branches:\n\n", ui.RenderAccent("🌿"))
for _, branch := range branches {
if branch == currentBranch {
fmt.Printf(" * %s\n", ui.StatusInProgressStyle.Render(branch))
} else {
fmt.Printf(" %s\n", branch)
}
}
fmt.Println()
return
}
// Create new branch
branchName := args[0]
if err := vs.Branch(ctx, branchName); err != nil {
FatalErrorRespectJSON("failed to create branch: %v", err)
}
if jsonOutput {
outputJSON(map[string]interface{}{
"created": branchName,
})
return
}
fmt.Printf("Created branch: %s\n", ui.RenderAccent(branchName))
},
}
func init() {
rootCmd.AddCommand(branchCmd)
}