Fix daemon auto-sync delete mutation not reflected in sync branch (#537)
Fix daemon auto-sync delete mutation not reflected in sync branch When deleting an issue with `bd delete <id> --force`, the daemon auto-sync now properly removes the deleted issue from the sync branch. **Problem:** The merge logic saw fewer local issues (due to deletion) and would re-add the deleted issue. **Solution:** Add `ForceOverwrite` option to bypass merge logic when mutations occur. Mutation-triggered exports are authoritative and should overwrite, not merge. Reviewed-by: stevey
This commit is contained in:
@@ -455,7 +455,10 @@ func performExport(ctx context.Context, store storage.Storage, autoCommit, autoP
|
||||
// Auto-commit if enabled (skip in git-free mode)
|
||||
if autoCommit && !skipGit {
|
||||
// Try sync branch commit first
|
||||
committed, err := syncBranchCommitAndPush(exportCtx, store, autoPush, log)
|
||||
// Use forceOverwrite=true because mutation-triggered exports (create, update, delete)
|
||||
// mean the local state is authoritative and should not be merged with worktree.
|
||||
// This is critical for delete mutations to be properly reflected in the sync branch.
|
||||
committed, err := syncBranchCommitAndPushWithOptions(exportCtx, store, autoPush, true, log)
|
||||
if err != nil {
|
||||
log.log("Sync branch commit failed: %v", err)
|
||||
return
|
||||
|
||||
@@ -14,9 +14,18 @@ import (
|
||||
"github.com/steveyegge/beads/internal/syncbranch"
|
||||
)
|
||||
|
||||
// syncBranchCommitAndPush commits JSONL to the sync branch using a worktree
|
||||
// Returns true if changes were committed, false if no changes or sync.branch not configured
|
||||
// syncBranchCommitAndPush commits JSONL to the sync branch using a worktree.
|
||||
// Returns true if changes were committed, false if no changes or sync.branch not configured.
|
||||
// This is a convenience wrapper that calls syncBranchCommitAndPushWithOptions with default options.
|
||||
func syncBranchCommitAndPush(ctx context.Context, store storage.Storage, autoPush bool, log daemonLogger) (bool, error) {
|
||||
return syncBranchCommitAndPushWithOptions(ctx, store, autoPush, false, log)
|
||||
}
|
||||
|
||||
// syncBranchCommitAndPushWithOptions commits JSONL to the sync branch using a worktree.
|
||||
// Returns true if changes were committed, false if no changes or sync.branch not configured.
|
||||
// If forceOverwrite is true, the local JSONL is copied to the worktree without merging,
|
||||
// which is necessary for delete mutations to be properly reflected in the sync branch.
|
||||
func syncBranchCommitAndPushWithOptions(ctx context.Context, store storage.Storage, autoPush, forceOverwrite bool, log daemonLogger) (bool, error) {
|
||||
// Check if any remote exists (bd-biwp: support local-only repos)
|
||||
if !hasGitRemote(ctx) {
|
||||
return true, nil // Skip sync branch commit/push in local-only mode
|
||||
@@ -77,7 +86,12 @@ func syncBranchCommitAndPush(ctx context.Context, store storage.Storage, autoPus
|
||||
return false, fmt.Errorf("failed to get relative JSONL path: %w", err)
|
||||
}
|
||||
|
||||
if err := wtMgr.SyncJSONLToWorktree(worktreePath, jsonlRelPath); err != nil {
|
||||
// Use SyncJSONLToWorktreeWithOptions to pass forceOverwrite flag.
|
||||
// When forceOverwrite is true (mutation-triggered sync, especially delete),
|
||||
// the local JSONL is copied directly without merging, ensuring deletions
|
||||
// are properly reflected in the sync branch.
|
||||
syncOpts := git.SyncOptions{ForceOverwrite: forceOverwrite}
|
||||
if err := wtMgr.SyncJSONLToWorktreeWithOptions(worktreePath, jsonlRelPath, syncOpts); err != nil {
|
||||
return false, fmt.Errorf("failed to sync JSONL to worktree: %w", err)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user