Skip to main content
Glama

git_diff

Compare differences between branches or commits in a Git repository using the 'git_diff' tool on the MCP Git Server. Simplify version control by analyzing changes with precision.

Instructions

Shows differences between branches or commits

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
repo_pathYes
targetYes

Implementation Reference

  • The core handler function implementing the git_diff tool logic. Executes git diff using dulwich Repo.git.diff with support for commit ranges (commit_range), two-commit comparison (base_commit/target_commit), target branch/commit, paths filtering, stat-only, name-only modes, parameter validation to prevent conflicts, size limiting with truncation warnings, and comprehensive error handling.
    def git_diff( repo: Repo, target: str | None = None, stat_only: bool = False, max_lines: int | None = None, name_only: bool = False, commit_range: str | None = None, base_commit: str | None = None, target_commit: str | None = None, paths: list[str] | None = None, ) -> str: """Get diff with advanced options including commit ranges and file filtering. Parameter Precedence (mutually exclusive - only one method should be used): 1. commit_range: Use git range syntax like "HEAD~1..HEAD" or "main..develop" 2. base_commit + target_commit: Compare two specific commits/branches 3. target: Compare working tree against specific branch/commit (default behavior) 4. None: Compare working tree against HEAD (fallback) Args: repo: Git repository object target: Branch/commit to diff against (conflicts with commit_range or base_commit/target_commit) stat_only: Show only file change statistics, not content max_lines: Limit output to specified number of lines (overridden by name_only/stat_only) name_only: Show only names of changed files commit_range: Git range syntax like "HEAD~1..HEAD" (conflicts with other diff methods) base_commit: Starting commit for comparison (requires target_commit) target_commit: Ending commit for comparison (requires base_commit) paths: Filter diff to specific files/directories Returns: Formatted diff output with validation warnings if applicable Raises: Returns error message if parameters are conflicting or invalid """ # Validate parameters for conflicts and security is_valid, validation_msg = _validate_diff_parameters( target=target, commit_range=commit_range, base_commit=base_commit, target_commit=target_commit, ) if not is_valid: return f"❌ Parameter validation failed: {validation_msg}" # If there's a warning, include it in the output validation_warning = validation_msg if validation_msg and is_valid else None try: # Build git diff arguments diff_args = [] # Determine what we're diffing diff_description = "" if commit_range: # Use commit range syntax like "HEAD~1..HEAD" diff_args.append(commit_range) diff_description = f"commit range {commit_range}" elif base_commit and target_commit: # Compare two specific commits diff_args.extend([base_commit, target_commit]) diff_description = f"{base_commit}...{target_commit}" elif target: # Compare against target branch/commit (original behavior) diff_args.append(target) diff_description = f"against {target}" else: # Default to comparing working tree against HEAD diff_args.append("HEAD") diff_description = "against HEAD" # Add options based on parameters if name_only: diff_args.append("--name-only") elif stat_only: diff_args.append("--stat") # Add specific paths if provided if paths: diff_args.extend(["--"] + paths) # Execute git diff with arguments diff_output = repo.git.diff(*diff_args) # Handle name-only output if name_only: result = ( f"Changed files {diff_description}:\n{diff_output}" if diff_output.strip() else f"No changes {diff_description}" ) if validation_warning: result = f"⚠️ {validation_warning}\n\n{result}" return result # Handle stat-only output if stat_only: result = ( f"Diff {diff_description} summary:\n{diff_output}" if diff_output.strip() else f"No differences {diff_description}" ) if validation_warning: result = f"⚠️ {validation_warning}\n\n{result}" return result # Apply size limiting for full diff output result = _apply_diff_size_limiting( diff_output, f"diff {diff_description}", stat_only, max_lines ) if validation_warning: result = f"⚠️ {validation_warning}\n\n{result}" return result except GitCommandError as e: return f"❌ Diff failed: {str(e)}" except Exception as e: return f"❌ Diff error: {str(e)}"
  • Pydantic input schema/model for the git_diff tool, defining all parameters including repo_path, target, stat_only, max_lines, name_only, commit_range, base_commit, target_commit, and paths.
    class GitDiff(BaseModel): repo_path: str target: str | None = None # Made optional for commit range scenarios stat_only: bool | None = False max_lines: int | None = None name_only: bool | None = False commit_range: str | None = None base_commit: str | None = None target_commit: str | None = None paths: list[str] | None = None
  • Tool registration in the central ToolRegistry. Defines the MCP Tool with name 'git_diff', description, inputSchema from GitDiff model, and metadata. The actual handler is set later via GitToolRouter.
    ToolDefinition( name=GitTools.DIFF, category=ToolCategory.GIT, description="Show differences between branches or commits", schema=GitDiff, handler=placeholder_handler, requires_repo=True,
  • Handler registration and wrapper creation in CallToolHandler._get_git_handlers(). Imports git_diff from git.operations and creates a wrapped handler with GitPython Repo integration, error handling decorators, and argument mapping.
    "git_diff": self._create_git_handler( git_diff, requires_repo=True, extra_args=["target", "stat_only", "max_lines", "name_only", "paths"], ),
  • Tool name definition in GitTools enum for consistent referencing across the codebase.
    DIFF = "git_diff" COMMIT = "git_commit"

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/MementoRC/mcp-git'

If you have feedback or need assistance with the MCP directory API, please join our Discord server