fix: use git diff count for totalFiles in merge preview

The merge preview was showing incorrect file counts because it only
counted files tracked by the semantic evolution tracker. Many files
(test files, config files, etc.) weren't being tracked, leading to
misleading "Files to merge: 0" displays when there were actually
multiple files changed.

Changes:
- Add _get_changed_files_from_git() helper to get actual changed files
- Use git diff count as authoritative totalFiles instead of tracker count
- Use git diff file list for the files array in preview response
- Always compare against 'main' branch (worktrees are created from main)

This ensures the UI shows the correct number of files that will be
merged, matching the git diff stats shown elsewhere in the UI.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
AndyMik90
2025-12-19 11:01:34 +01:00
parent 71535581c2
commit 46d2536600
+61 -2
View File
@@ -5,6 +5,7 @@ Workspace Commands
CLI commands for workspace management (merge, review, discard, list, cleanup)
"""
import subprocess
import sys
from pathlib import Path
@@ -29,6 +30,44 @@ from workspace import (
from .utils import print_banner
def _get_changed_files_from_git(worktree_path: Path, base_branch: str = "main") -> list[str]:
"""
Get list of changed files from git diff between base branch and HEAD.
Args:
worktree_path: Path to the worktree
base_branch: Base branch to compare against (default: main)
Returns:
List of changed file paths
"""
try:
result = subprocess.run(
["git", "diff", "--name-only", f"{base_branch}...HEAD"],
cwd=worktree_path,
capture_output=True,
text=True,
check=True,
)
files = [f.strip() for f in result.stdout.strip().split("\n") if f.strip()]
return files
except subprocess.CalledProcessError:
# Fallback: try without the three-dot notation
try:
result = subprocess.run(
["git", "diff", "--name-only", base_branch, "HEAD"],
cwd=worktree_path,
capture_output=True,
text=True,
check=True,
)
files = [f.strip() for f in result.stdout.strip().split("\n") if f.strip()]
return files
except subprocess.CalledProcessError:
return []
# Import debug utilities
try:
from debug import (
@@ -381,6 +420,17 @@ def handle_merge_preview_command(project_dir: Path, spec_name: str) -> dict:
# First, check for git-level conflicts (diverged branches)
git_conflicts = _check_git_merge_conflicts(project_dir, spec_name)
# Get actual changed files from git diff (this is the authoritative count)
# Always compare against 'main' since worktrees are created from main
# The git_conflicts base_branch might be the current branch (e.g., version/2.5.5)
# which would give an incorrect diff
all_changed_files = _get_changed_files_from_git(worktree_path, "main")
debug(
MODULE,
f"Git diff shows {len(all_changed_files)} changed files",
changed_files=all_changed_files[:10], # Log first 10
)
debug(MODULE, "Initializing MergeOrchestrator for preview...")
# Initialize the orchestrator
@@ -456,9 +506,15 @@ def handle_merge_preview_command(project_dir: Path, spec_name: str) -> dict:
f for f in git_conflicts.get("conflicting_files", []) if not is_lock_file(f)
]
# Use git diff file count as the authoritative totalFiles count
# The semantic tracker may not track all files (e.g., test files, config files)
# but we want to show the user all files that will be merged
total_files_from_git = len(all_changed_files)
result = {
"success": True,
"files": preview.get("files_to_merge", []),
# Use git diff files as the authoritative list of files to merge
"files": all_changed_files,
"conflicts": conflicts,
"gitConflicts": {
"hasConflicts": git_conflicts["has_conflicts"]
@@ -470,7 +526,8 @@ def handle_merge_preview_command(project_dir: Path, spec_name: str) -> dict:
"specBranch": git_conflicts["spec_branch"],
},
"summary": {
"totalFiles": summary.get("total_files", 0),
# Use git diff count, not semantic tracker count
"totalFiles": total_files_from_git,
"conflictFiles": conflict_files,
"totalConflicts": total_conflicts,
"autoMergeable": summary.get("auto_mergeable", 0),
@@ -485,6 +542,8 @@ def handle_merge_preview_command(project_dir: Path, spec_name: str) -> dict:
MODULE,
"Merge preview complete",
total_files=result["summary"]["totalFiles"],
total_files_source="git_diff",
semantic_tracked_files=summary.get("total_files", 0),
total_conflicts=result["summary"]["totalConflicts"],
has_git_conflicts=git_conflicts["has_conflicts"],
auto_mergeable=result["summary"]["autoMergeable"],