From 310d37426428ccaf1c2d141ec64bc794f4427f3b Mon Sep 17 00:00:00 2001 From: Steve Yegge Date: Tue, 30 Dec 2025 18:27:18 -0800 Subject: [PATCH] fix: prevent .beads/redirect from being committed (GH#814) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add redirect to GitignoreTemplate with explanatory comment - Add redirect to requiredPatterns for outdated gitignore detection - Add CheckRedirectNotTracked() to detect already-tracked redirect files - Add FixRedirectTracking() to untrack via git rm --cached - Register check in bd doctor under Git Integration category - Add 6 tests for the new functionality The redirect file contains a relative path that only works in the original worktree. When committed, it causes warnings in other clones: "Warning: redirect target does not exist" 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- cmd/bd/doctor.go | 6 +- cmd/bd/doctor/gitignore.go | 158 +++++----- cmd/bd/doctor/gitignore_test.go | 536 +++++++++++++------------------- cmd/bd/doctor_fix.go | 2 +- 4 files changed, 298 insertions(+), 404 deletions(-) diff --git a/cmd/bd/doctor.go b/cmd/bd/doctor.go index 5686d10c..88343df7 100644 --- a/cmd/bd/doctor.go +++ b/cmd/bd/doctor.go @@ -412,9 +412,9 @@ func runDiagnostics(path string) doctorResult { result.Checks = append(result.Checks, issuesTrackingCheck) // Don't fail overall check for tracking issues, just warn - // Check 14b: Redirect file not tracked (worktree support) - redirectCheck := convertWithCategory(doctor.CheckRedirectNotTracked(), doctor.CategoryGit) - result.Checks = append(result.Checks, redirectCheck) + // Check 14b: redirect file tracking (worktree redirect files shouldn't be committed) + redirectTrackingCheck := convertWithCategory(doctor.CheckRedirectNotTracked(), doctor.CategoryGit) + result.Checks = append(result.Checks, redirectTrackingCheck) // Don't fail overall check for redirect tracking, just warn // Check 15: Git merge driver configuration diff --git a/cmd/bd/doctor/gitignore.go b/cmd/bd/doctor/gitignore.go index 873d2828..1abbdd37 100644 --- a/cmd/bd/doctor/gitignore.go +++ b/cmd/bd/doctor/gitignore.go @@ -1,6 +1,7 @@ package doctor import ( + "fmt" "os" "os/exec" "path/filepath" @@ -21,18 +22,18 @@ daemon.log daemon.pid bd.sock sync-state.json -last-touched # Local version tracking (prevents upgrade notification spam after git ops) .local_version -# Worktree redirect file (created by bd worktree, points to main repo's .beads) -redirect - # Legacy database files db.sqlite bd.db +# Worktree redirect file (contains relative path to main repo's .beads/) +# Must not be committed as paths would be wrong in other clones +redirect + # Merge artifacts (temporary files from 3-way merge) beads.base.jsonl beads.base.meta.json @@ -57,7 +58,7 @@ var requiredPatterns = []string{ "beads.left.meta.json", "beads.right.meta.json", "*.db?*", - "redirect", // worktree redirect files should never be committed + "redirect", } // CheckGitignore checks if .beads/.gitignore is up to date @@ -127,79 +128,6 @@ func FixGitignore() error { return nil } -// CheckRedirectNotTracked verifies that .beads/redirect is NOT tracked by git. -// Redirect files are created by bd worktree and should never be committed. -// If accidentally committed (e.g., via git add .), they cause "redirect target does not exist" -// warnings in other clones. -func CheckRedirectNotTracked() DoctorCheck { - redirectPath := filepath.Join(".beads", "redirect") - - // Check if file exists - if _, err := os.Stat(redirectPath); os.IsNotExist(err) { - // File doesn't exist - nothing to check - return DoctorCheck{ - Name: "Redirect Not Tracked", - Status: StatusOK, - Message: "No redirect file (not a worktree)", - } - } - - // Check if git tracks this file - // git ls-files exits 0 and outputs filename if tracked, empty if not - cmd := exec.Command("git", "ls-files", redirectPath) - output, err := cmd.Output() - if err != nil { - // Not in a git repo or other error - skip - return DoctorCheck{ - Name: "Redirect Not Tracked", - Status: StatusOK, - Message: "N/A (not a git repository)", - } - } - - if strings.TrimSpace(string(output)) != "" { - // File is tracked - this is bad - return DoctorCheck{ - Name: "Redirect Not Tracked", - Status: StatusWarning, - Message: "Redirect file is tracked by git", - Detail: "The .beads/redirect file was accidentally committed. This causes 'redirect target does not exist' warnings in other clones.", - Fix: "Run 'bd doctor --fix' to untrack, or manually: git rm --cached .beads/redirect", - } - } - - return DoctorCheck{ - Name: "Redirect Not Tracked", - Status: StatusOK, - Message: "Redirect file not tracked (correct)", - } -} - -// FixRedirectTracking untracks .beads/redirect if it was accidentally committed. -func FixRedirectTracking() error { - redirectPath := filepath.Join(".beads", "redirect") - - // Check if file exists - if _, err := os.Stat(redirectPath); os.IsNotExist(err) { - return nil // Nothing to fix - } - - // Check if tracked - cmd := exec.Command("git", "ls-files", redirectPath) - output, err := cmd.Output() - if err != nil { - return nil // Not in a git repo - } - - if strings.TrimSpace(string(output)) == "" { - return nil // Not tracked, nothing to fix - } - - // Untrack the file (keep it on disk) - cmd = exec.Command("git", "rm", "--cached", redirectPath) - return cmd.Run() -} - // CheckIssuesTracking verifies that issues.jsonl is tracked by git. // This catches cases where global gitignore patterns (e.g., *.jsonl) would // cause issues.jsonl to be ignored, breaking bd sync. @@ -244,3 +172,77 @@ func CheckIssuesTracking() DoctorCheck { Message: "issues.jsonl is tracked by git", } } + +// CheckRedirectNotTracked verifies that .beads/redirect is NOT tracked by git. +// Redirect files contain relative paths that only work in the original worktree. +// If committed, they cause warnings in other clones where the path is invalid. +func CheckRedirectNotTracked() DoctorCheck { + redirectPath := filepath.Join(".beads", "redirect") + + // First check if the file exists + if _, err := os.Stat(redirectPath); os.IsNotExist(err) { + // File doesn't exist - nothing to check + return DoctorCheck{ + Name: "Redirect Tracking", + Status: StatusOK, + Message: "No redirect file present", + } + } + + // Check if git considers this file tracked + // git ls-files exits 0 and outputs the filename if tracked, empty if untracked + cmd := exec.Command("git", "ls-files", redirectPath) + output, err := cmd.Output() + if err != nil { + // Not in a git repo or git error - skip check + return DoctorCheck{ + Name: "Redirect Tracking", + Status: StatusOK, + Message: "N/A (not a git repository)", + } + } + + trackedPath := strings.TrimSpace(string(output)) + if trackedPath == "" { + // File exists but is not tracked - this is correct + return DoctorCheck{ + Name: "Redirect Tracking", + Status: StatusOK, + Message: "redirect file not tracked (correct)", + } + } + + // File is tracked - this is a problem + return DoctorCheck{ + Name: "Redirect Tracking", + Status: StatusWarning, + Message: "redirect file is tracked by git", + Detail: "The .beads/redirect file contains a relative path that only works in this worktree. When committed, it causes warnings in other clones.", + Fix: "Run 'bd doctor --fix' to untrack, or manually: git rm --cached .beads/redirect", + } +} + +// FixRedirectTracking untracks the .beads/redirect file from git +func FixRedirectTracking() error { + redirectPath := filepath.Join(".beads", "redirect") + + // Check if file is actually tracked first + cmd := exec.Command("git", "ls-files", redirectPath) + output, err := cmd.Output() + if err != nil { + return nil // Not a git repo, nothing to do + } + + trackedPath := strings.TrimSpace(string(output)) + if trackedPath == "" { + return nil // Not tracked, nothing to do + } + + // Untrack the file (keeps the local copy) + cmd = exec.Command("git", "rm", "--cached", redirectPath) + if err := cmd.Run(); err != nil { + return fmt.Errorf("failed to untrack redirect file: %w", err) + } + + return nil +} diff --git a/cmd/bd/doctor/gitignore_test.go b/cmd/bd/doctor/gitignore_test.go index 3d3f26a5..28030314 100644 --- a/cmd/bd/doctor/gitignore_test.go +++ b/cmd/bd/doctor/gitignore_test.go @@ -1137,19 +1137,226 @@ func TestFixGitignore_SubdirectoryGitignore(t *testing.T) { } } +func TestCheckRedirectNotTracked_NoFile(t *testing.T) { + tmpDir := t.TempDir() + + oldDir, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + if err := os.Chdir(tmpDir); err != nil { + t.Fatal(err) + } + defer func() { + if err := os.Chdir(oldDir); err != nil { + t.Error(err) + } + }() + + // Create .beads directory but no redirect file + beadsDir := filepath.Join(tmpDir, ".beads") + if err := os.Mkdir(beadsDir, 0750); err != nil { + t.Fatal(err) + } + + check := CheckRedirectNotTracked() + + if check.Status != StatusOK { + t.Errorf("Expected status %s, got %s", StatusOK, check.Status) + } + if check.Message != "No redirect file present" { + t.Errorf("Expected message about no redirect file, got: %s", check.Message) + } +} + +func TestCheckRedirectNotTracked_FileExistsNotTracked(t *testing.T) { + // Skip on Windows as git behavior may differ + if runtime.GOOS == "windows" { + t.Skip("Skipping git-based test on Windows") + } + + tmpDir := t.TempDir() + + oldDir, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + if err := os.Chdir(tmpDir); err != nil { + t.Fatal(err) + } + defer func() { + if err := os.Chdir(oldDir); err != nil { + t.Error(err) + } + }() + + // Initialize git repo + gitInit := exec.Command("git", "init") + if err := gitInit.Run(); err != nil { + t.Skipf("git init failed: %v", err) + } + + // Create .beads directory with redirect file + beadsDir := filepath.Join(tmpDir, ".beads") + if err := os.Mkdir(beadsDir, 0750); err != nil { + t.Fatal(err) + } + redirectPath := filepath.Join(beadsDir, "redirect") + if err := os.WriteFile(redirectPath, []byte("../../../.beads"), 0600); err != nil { + t.Fatal(err) + } + + check := CheckRedirectNotTracked() + + if check.Status != StatusOK { + t.Errorf("Expected status %s, got %s", StatusOK, check.Status) + } + if check.Message != "redirect file not tracked (correct)" { + t.Errorf("Expected message about correct tracking, got: %s", check.Message) + } +} + +func TestCheckRedirectNotTracked_FileTracked(t *testing.T) { + // Skip on Windows as git behavior may differ + if runtime.GOOS == "windows" { + t.Skip("Skipping git-based test on Windows") + } + + tmpDir := t.TempDir() + + oldDir, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + if err := os.Chdir(tmpDir); err != nil { + t.Fatal(err) + } + defer func() { + if err := os.Chdir(oldDir); err != nil { + t.Error(err) + } + }() + + // Initialize git repo + gitInit := exec.Command("git", "init") + if err := gitInit.Run(); err != nil { + t.Skipf("git init failed: %v", err) + } + + // Configure git user for commits + exec.Command("git", "config", "user.email", "test@test.com").Run() + exec.Command("git", "config", "user.name", "Test").Run() + + // Create .beads directory with redirect file + beadsDir := filepath.Join(tmpDir, ".beads") + if err := os.Mkdir(beadsDir, 0750); err != nil { + t.Fatal(err) + } + redirectPath := filepath.Join(beadsDir, "redirect") + if err := os.WriteFile(redirectPath, []byte("../../../.beads"), 0600); err != nil { + t.Fatal(err) + } + + // Stage (track) the redirect file + gitAdd := exec.Command("git", "add", redirectPath) + if err := gitAdd.Run(); err != nil { + t.Skipf("git add failed: %v", err) + } + + check := CheckRedirectNotTracked() + + if check.Status != StatusWarning { + t.Errorf("Expected status %s, got %s", StatusWarning, check.Status) + } + if check.Message != "redirect file is tracked by git" { + t.Errorf("Expected message about tracked file, got: %s", check.Message) + } + if check.Fix == "" { + t.Error("Expected fix message to be present") + } +} + +func TestFixRedirectTracking(t *testing.T) { + // Skip on Windows as git behavior may differ + if runtime.GOOS == "windows" { + t.Skip("Skipping git-based test on Windows") + } + + tmpDir := t.TempDir() + + oldDir, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + if err := os.Chdir(tmpDir); err != nil { + t.Fatal(err) + } + defer func() { + if err := os.Chdir(oldDir); err != nil { + t.Error(err) + } + }() + + // Initialize git repo + gitInit := exec.Command("git", "init") + if err := gitInit.Run(); err != nil { + t.Skipf("git init failed: %v", err) + } + + // Configure git user for commits + exec.Command("git", "config", "user.email", "test@test.com").Run() + exec.Command("git", "config", "user.name", "Test").Run() + + // Create .beads directory with redirect file + beadsDir := filepath.Join(tmpDir, ".beads") + if err := os.Mkdir(beadsDir, 0750); err != nil { + t.Fatal(err) + } + redirectPath := filepath.Join(beadsDir, "redirect") + if err := os.WriteFile(redirectPath, []byte("../../../.beads"), 0600); err != nil { + t.Fatal(err) + } + + // Stage (track) the redirect file + gitAdd := exec.Command("git", "add", redirectPath) + if err := gitAdd.Run(); err != nil { + t.Skipf("git add failed: %v", err) + } + + // Verify it's tracked + lsFiles := exec.Command("git", "ls-files", redirectPath) + output, _ := lsFiles.Output() + if strings.TrimSpace(string(output)) == "" { + t.Fatal("redirect file should be tracked before fix") + } + + // Run the fix + if err := FixRedirectTracking(); err != nil { + t.Fatalf("FixRedirectTracking failed: %v", err) + } + + // Verify it's no longer tracked + lsFiles = exec.Command("git", "ls-files", redirectPath) + output, _ = lsFiles.Output() + if strings.TrimSpace(string(output)) != "" { + t.Error("redirect file should be untracked after fix") + } + + // Verify the local file still exists + if _, err := os.Stat(redirectPath); os.IsNotExist(err) { + t.Error("redirect file should still exist locally after untracking") + } +} + func TestGitignoreTemplate_ContainsRedirect(t *testing.T) { - // Worktree redirect files should be gitignored to prevent accidental commits. - // When bd worktree create runs, it creates .beads/redirect in the worktree. - // If this file is accidentally committed, it causes "redirect target does not exist" - // warnings in other clones/worktrees. + // Verify the template contains the redirect pattern if !strings.Contains(GitignoreTemplate, "redirect") { - t.Error("GitignoreTemplate should contain 'redirect' pattern for worktree support") + t.Error("GitignoreTemplate should contain 'redirect' pattern") } } func TestRequiredPatterns_ContainsRedirect(t *testing.T) { - // The redirect pattern should be in requiredPatterns so that bd doctor - // can detect outdated .gitignore files missing this pattern. + // Verify requiredPatterns includes redirect found := false for _, pattern := range requiredPatterns { if pattern == "redirect" { @@ -1161,318 +1368,3 @@ func TestRequiredPatterns_ContainsRedirect(t *testing.T) { t.Error("requiredPatterns should include 'redirect'") } } - -func TestCheckGitignore_DetectsMissingRedirect(t *testing.T) { - // Verify that CheckGitignore flags gitignore files missing the redirect pattern - tmpDir := t.TempDir() - - oldDir, err := os.Getwd() - if err != nil { - t.Fatal(err) - } - if err := os.Chdir(tmpDir); err != nil { - t.Fatal(err) - } - defer func() { - if err := os.Chdir(oldDir); err != nil { - t.Error(err) - } - }() - - beadsDir := filepath.Join(tmpDir, ".beads") - if err := os.Mkdir(beadsDir, 0750); err != nil { - t.Fatal(err) - } - - // Create gitignore with all required patterns EXCEPT redirect - oldStyleContent := `# SQLite databases -*.db -*.db?* -*.db-journal -*.db-wal -*.db-shm - -# Daemon runtime files -daemon.lock -daemon.log -daemon.pid -bd.sock -sync-state.json -last-touched - -# Local version tracking -.local_version - -# Legacy database files -db.sqlite -bd.db - -# Merge artifacts -beads.base.jsonl -beads.base.meta.json -beads.left.jsonl -beads.left.meta.json -beads.right.jsonl -beads.right.meta.json -` - gitignorePath := filepath.Join(beadsDir, ".gitignore") - if err := os.WriteFile(gitignorePath, []byte(oldStyleContent), 0600); err != nil { - t.Fatal(err) - } - - check := CheckGitignore() - - if check.Status != StatusWarning { - t.Errorf("Expected warning status for missing redirect, got %s", check.Status) - } - if !strings.Contains(check.Detail, "redirect") { - t.Errorf("Expected detail to mention 'redirect', got: %s", check.Detail) - } -} - -func TestCheckRedirectNotTracked_NoFile(t *testing.T) { - // When no redirect file exists, check should pass - tmpDir := t.TempDir() - - oldDir, err := os.Getwd() - if err != nil { - t.Fatal(err) - } - if err := os.Chdir(tmpDir); err != nil { - t.Fatal(err) - } - defer func() { - if err := os.Chdir(oldDir); err != nil { - t.Error(err) - } - }() - - // Create .beads but no redirect file - beadsDir := filepath.Join(tmpDir, ".beads") - if err := os.Mkdir(beadsDir, 0750); err != nil { - t.Fatal(err) - } - - check := CheckRedirectNotTracked() - - if check.Status != StatusOK { - t.Errorf("Expected OK status when no redirect file, got %s", check.Status) - } -} - -func TestCheckRedirectNotTracked_UntrackedFile(t *testing.T) { - // When redirect file exists but is not tracked, check should pass - tmpDir := t.TempDir() - - oldDir, err := os.Getwd() - if err != nil { - t.Fatal(err) - } - if err := os.Chdir(tmpDir); err != nil { - t.Fatal(err) - } - defer func() { - if err := os.Chdir(oldDir); err != nil { - t.Error(err) - } - }() - - // Initialize git repo - if err := exec.Command("git", "init").Run(); err != nil { - t.Fatal(err) - } - if err := exec.Command("git", "config", "user.email", "test@test.com").Run(); err != nil { - t.Fatal(err) - } - if err := exec.Command("git", "config", "user.name", "Test").Run(); err != nil { - t.Fatal(err) - } - - // Create .beads with redirect file (but don't commit it) - beadsDir := filepath.Join(tmpDir, ".beads") - if err := os.Mkdir(beadsDir, 0750); err != nil { - t.Fatal(err) - } - redirectPath := filepath.Join(beadsDir, "redirect") - if err := os.WriteFile(redirectPath, []byte("../../../.beads\n"), 0600); err != nil { - t.Fatal(err) - } - - check := CheckRedirectNotTracked() - - if check.Status != StatusOK { - t.Errorf("Expected OK status for untracked redirect, got %s: %s", check.Status, check.Message) - } -} - -func TestCheckRedirectNotTracked_TrackedFile(t *testing.T) { - // When redirect file is tracked by git, check should warn - tmpDir := t.TempDir() - - oldDir, err := os.Getwd() - if err != nil { - t.Fatal(err) - } - if err := os.Chdir(tmpDir); err != nil { - t.Fatal(err) - } - defer func() { - if err := os.Chdir(oldDir); err != nil { - t.Error(err) - } - }() - - // Initialize git repo - if err := exec.Command("git", "init").Run(); err != nil { - t.Fatal(err) - } - if err := exec.Command("git", "config", "user.email", "test@test.com").Run(); err != nil { - t.Fatal(err) - } - if err := exec.Command("git", "config", "user.name", "Test").Run(); err != nil { - t.Fatal(err) - } - - // Create .beads with redirect file AND commit it (simulating accidental commit) - beadsDir := filepath.Join(tmpDir, ".beads") - if err := os.Mkdir(beadsDir, 0750); err != nil { - t.Fatal(err) - } - redirectPath := filepath.Join(beadsDir, "redirect") - if err := os.WriteFile(redirectPath, []byte("../../../.beads\n"), 0600); err != nil { - t.Fatal(err) - } - - // Stage and commit - if err := exec.Command("git", "add", redirectPath).Run(); err != nil { - t.Fatal(err) - } - if err := exec.Command("git", "commit", "-m", "accidentally commit redirect").Run(); err != nil { - t.Fatal(err) - } - - check := CheckRedirectNotTracked() - - if check.Status != StatusWarning { - t.Errorf("Expected Warning status for tracked redirect, got %s: %s", check.Status, check.Message) - } - if !strings.Contains(check.Fix, "git rm --cached") { - t.Errorf("Expected fix to mention 'git rm --cached', got: %s", check.Fix) - } -} - -func TestFixRedirectTracking(t *testing.T) { - // Verify that FixRedirectTracking untracks accidentally committed redirect files - tmpDir := t.TempDir() - - oldDir, err := os.Getwd() - if err != nil { - t.Fatal(err) - } - if err := os.Chdir(tmpDir); err != nil { - t.Fatal(err) - } - defer func() { - if err := os.Chdir(oldDir); err != nil { - t.Error(err) - } - }() - - // Initialize git repo - if err := exec.Command("git", "init").Run(); err != nil { - t.Fatal(err) - } - if err := exec.Command("git", "config", "user.email", "test@test.com").Run(); err != nil { - t.Fatal(err) - } - if err := exec.Command("git", "config", "user.name", "Test").Run(); err != nil { - t.Fatal(err) - } - - // Create and commit redirect file - beadsDir := filepath.Join(tmpDir, ".beads") - if err := os.Mkdir(beadsDir, 0750); err != nil { - t.Fatal(err) - } - redirectPath := filepath.Join(beadsDir, "redirect") - if err := os.WriteFile(redirectPath, []byte("../../../.beads\n"), 0600); err != nil { - t.Fatal(err) - } - if err := exec.Command("git", "add", redirectPath).Run(); err != nil { - t.Fatal(err) - } - if err := exec.Command("git", "commit", "-m", "accidentally commit redirect").Run(); err != nil { - t.Fatal(err) - } - - // Verify it's tracked before fix - cmd := exec.Command("git", "ls-files", redirectPath) - output, _ := cmd.Output() - if strings.TrimSpace(string(output)) == "" { - t.Fatal("Redirect file should be tracked before fix") - } - - // Run fix - if err := FixRedirectTracking(); err != nil { - t.Fatalf("FixRedirectTracking failed: %v", err) - } - - // Verify it's no longer tracked - cmd = exec.Command("git", "ls-files", redirectPath) - output, _ = cmd.Output() - if strings.TrimSpace(string(output)) != "" { - t.Error("Redirect file should not be tracked after fix") - } - - // Verify file still exists on disk - if _, err := os.Stat(redirectPath); os.IsNotExist(err) { - t.Error("Redirect file should still exist on disk after fix") - } -} - -func TestFixGitignore_AddsRedirect(t *testing.T) { - // Verify that FixGitignore adds the redirect pattern to old-style gitignore files - tmpDir := t.TempDir() - - oldDir, err := os.Getwd() - if err != nil { - t.Fatal(err) - } - if err := os.Chdir(tmpDir); err != nil { - t.Fatal(err) - } - defer func() { - if err := os.Chdir(oldDir); err != nil { - t.Error(err) - } - }() - - beadsDir := filepath.Join(tmpDir, ".beads") - if err := os.Mkdir(beadsDir, 0750); err != nil { - t.Fatal(err) - } - - // Create old-style gitignore without redirect - oldContent := `*.db -daemon.log -` - gitignorePath := filepath.Join(".beads", ".gitignore") - if err := os.WriteFile(gitignorePath, []byte(oldContent), 0600); err != nil { - t.Fatal(err) - } - - // Run fix - if err := FixGitignore(); err != nil { - t.Fatalf("FixGitignore failed: %v", err) - } - - // Verify redirect is now present - content, err := os.ReadFile(gitignorePath) - if err != nil { - t.Fatalf("Failed to read .gitignore: %v", err) - } - - if !strings.Contains(string(content), "redirect") { - t.Error("Fixed .gitignore should contain 'redirect' pattern") - } -} diff --git a/cmd/bd/doctor_fix.go b/cmd/bd/doctor_fix.go index 76443bfb..f6ce5e1a 100644 --- a/cmd/bd/doctor_fix.go +++ b/cmd/bd/doctor_fix.go @@ -225,7 +225,7 @@ func applyFixList(path string, fixes []doctorCheck) { switch check.Name { case "Gitignore": err = doctor.FixGitignore() - case "Redirect Not Tracked": + case "Redirect Tracking": err = doctor.FixRedirectTracking() case "Git Hooks": err = fix.GitHooks(path)