merge-index Git Command Guide
The git merge-index command runs a specified merge program for all files in the Git index that need merging during merge conflicts or other index operations. It passes SHA-1 hashes, file modes, and paths to the merge program for conflict resolution.
git merge-index Syntax:
Section titled “git merge-index Syntax:”git merge-index [-o] [-q] <merge-program> (-a | ( [--] <file>...) )Execution Control Options:
Section titled “Execution Control Options:”| Option | Description |
|---|---|
-o | Skip the check for files needing merging |
-q, --quiet | Do not complain about failed merges |
-a, --all | Run merge against all files in the index that need merging |
-- | Do not interpret any more arguments as options |
Parameters:
Section titled “Parameters:”| Parameter | Description |
|---|---|
<merge-program> | Program to run for each merge operation |
<file>... | Specific files to run merge on (if not using -a) |
Understanding Index Merging:
Section titled “Understanding Index Merging:”Index States During Merge:
Section titled “Index States During Merge:”Index Entry States:0: Regular file (no conflict)1: Base (common ancestor) - created during merge2: Ours (HEAD version)3: Theirs (MERGE_HEAD version)
merge-index processes entries with multiple versions (stages)Merge Program Interface:
Section titled “Merge Program Interface:”The merge program receives these arguments:
SHA1-base- Base version (or empty string)SHA1-our- Our versionSHA1-their- Their versionfilename- File being mergedmode-base- Base file permissionsmode-our- Our file permissionsmode-their- Their file permissions
Basic Usage Examples:
Section titled “Basic Usage Examples:”Run Merge on All Conflicted Files:
Section titled “Run Merge on All Conflicted Files:”# Run merge on all files needing itgit merge-index git-merge-one-file -a
# Silent operation (don't complain about failures)git merge-index -q git-merge-one-file -aProcess Specific Files:
Section titled “Process Specific Files:”# Merge only specific conflicted filesgit merge-index git-merge-one-file conflicted-file.txt another-conflict.c
# Use different merge tools for different file typesgit merge-index -a -- \ git merge-one-file-script.shCustom Merge Programs:
Section titled “Custom Merge Programs:”# Use git merge-file for three-way merginggit merge-index git merge-file -a
# Custom merge scriptcat > my-merge-prog << 'EOF'#!/bin/bash# Arguments: $1=base-sha, $2=our-sha, $3=their-sha, $4=file, $5=mode-base, $6=mode-our, $7=mode-their
echo "Merging $4"echo "Base: $1 ($5)"echo "Ours: $2 ($6)"echo "Theirs: $3 ($7)"
# Your custom merge logic hereexit 0EOF
chmod +x my-merge-proggit merge-index ./my-merge-prog -aAdvanced Merge Scenarios:
Section titled “Advanced Merge Scenarios:”Conflict Resolution Strategies:
Section titled “Conflict Resolution Strategies:”#!/bin/bash# Smart conflict resolution based on file type
resolve_conflicts() { local resolver_script=$(mktemp)
cat > "$resolver_script" << 'EOF'#!/bin/bashbase_sha=$1our_sha=$2their_sha=$3filename=$4
case "${filename##*.}" in json|yml|yaml) # Prefer our changes for config files git cat-file -p "$our_sha" > "$filename" echo "Resolved $filename: kept our version" ;; md|txt|rst) # Merge documentation with union strategy git merge-file --union "$filename" <(git cat-file -p "$base_sha") <(git cat-file -p "$their_sha") echo "Resolved $filename: union merge" ;; *) # Use standard merge for source code if git merge-file "$filename" <(git cat-file -p "$base_sha") \ <(git cat-file -p "$our_sha") \ <(git cat-file -p "$their_sha"); then echo "Resolved $filename: automatic merge" else echo "Conflict in $filename requires manual resolution" exit 1 fi ;;esacEOF
chmod +x "$resolver_script" git merge-index "$resolver_script" -a rm "$resolver_script"}
resolve_conflictsDebugging Index State:
Section titled “Debugging Index State:”# Show current index state for merging filesgit ls-files --stage | grep "^100644 [123] " | head -10
# Count files needing merge by stagefor stage in 1 2 3; do echo "Stage $stage files: $(git ls-files --stage | grep "^...... $stage " | wc -l)"done
# Show conflicted filesgit diff --cached --name-only | while read file; do git ls-files --stage "$file" | awk '{print $3}' | sort | uniq | wc -l | tr -d '\n' echo " versions of $file"doneBatch Merge Processing:
Section titled “Batch Merge Processing:”# Process large numbers of conflicts in batchesmerge_in_batches() { local batch_size="${1:-10}" local temp_script=$(mktemp)
cat > "$temp_script" << 'EOF'#!/bin/bashecho "Processing merge for $4"git merge-one-file "$4" 2>/dev/null && echo "✓ $4" || echo "✗ $4 needs manual merge"EOF
chmod +x "$temp_script"
# Process files in batches git ls-files -u | awk '{print $4}' | sort | uniq | \ while read file; do echo "$file" done | \ xargs -n "$batch_size" | \ while read batch; do echo "Processing batch: $batch" for file in $batch; do bash "$temp_script" "" "" "" "$file" done echo "--- End of batch ---" done
rm "$temp_script"}
merge_in_batches 5Configuration and Customization:
Section titled “Configuration and Customization:”Default Merge Behavior:
Section titled “Default Merge Behavior:”# Configure default merge drivergit config merge.default driver-name
# Configure merge tool for index operationsgit config mergetool.default name
# Set up automatic merge for certain file typesecho "*.json merge=our-json" >> .gitattributesgit config merge.our-json.driver "cp %A %B" # Always take ours for JSONCustom Merge Drivers:
Section titled “Custom Merge Drivers:”# Set up custom merge drivergit config merge.jsonmerge.name "resolve JSON conflicts"git config merge.jsonmerge.driver "jq -s '.[0] * .[1]' %O > %A"
# Use in .gitattributesecho "*.json merge=jsonmerge" >> .gitattributesPerformance Optimization:
Section titled “Performance Optimization:”# Disable auto-GC during merge operationsgit config gc.auto 0
# Use parallel processing for multiple filesgit merge-index -a --parallel 4 git-merge-one-file-script
# Limit merge operationsulimit -t 300 # 5 minute timeout per mergegit merge-index timeout 300 git-merge-one-file -aIntegration with Git Workflows:
Section titled “Integration with Git Workflows:”Pre-merge Validation:
Section titled “Pre-merge Validation:”#!/bin/bash# Validate merge will succeed before attempting
validate_index_merge() { local merge_program="${1:-git-merge-one-file}" local test_mode="${2:-false}"
# Create test environment local test_dir=$(mktemp -d) local failures=0
# Copy conflicted files to test git ls-files -u | awk '{print $4}' | sort | uniq | \ while read file; do mkdir -p "$test_dir/$(dirname "$file")" cp "$file" "$test_dir/$file" done
# Test merges for file in "$test_dir"/*; do if [ "$test_mode" = "true" ]; then echo "Would test: $(basename "$file")" continue fi
# Create test versions git show :1:"$file" > "$file.base" 2>/dev/null || echo "" > "$file.base" git show :2:"$file" > "$file.ours" 2>/dev/null git show :3:"$file" > "$file.theirs" 2>/dev/null
if "$merge_program" "" "" "" "$file" "" "" "" 2>/dev/null; then echo "✓ $(basename "$file") would merge cleanly" else echo "✗ $(basename "$file") would have conflicts" failures=$((failures + 1)) fi
rm -f "$file.base" "$file.ours" "$file.theirs" done
rm -rf "$test_dir"
if [ "$failures" -eq 0 ]; then echo "All files can be merged automatically" return 0 else echo "$failures file(s) would have merge conflicts" return 1 fi}
validate_index_mergeAutomated Conflict Resolution:
Section titled “Automated Conflict Resolution:”# Automated resolution based on rulesauto_resolve_conflicts() { local resolution_script=$(mktemp)
cat > "$resolution_script" << 'EOF'#!/bin/bashbase_sha=$1our_sha=$2their_sha=$3filename=$4base_mode=$5our_mode=$6their_mode=$7
# Rule-based resolutioncase "$filename" in # Always take our version for generated files *.lock|*.min.js) git cat-file -p "$our_sha" > "$filename" echo "Resolved $filename: kept our version" ;;
# Always take their version for third-party node_modules/*|vendor/*) git cat-file -p "$their_sha" > "$filename" echo "Resolved $filename: kept their version" ;;
# Use git merge-file for code files *.c|*.cpp|*.py|*.js) git merge-file "$filename" \ <(git cat-file -p "$base_sha" 2>/dev/null || echo "") \ <(git cat-file -p "$our_sha") \ <(git cat-file -p "$their_sha") echo "Resolved $filename: three-way merge" ;;
# Manual handling for config files *.json|*.yml|*.yaml) echo "Manual resolution needed for $filename" exit 1 # Signal manual intervention needed ;;
*) # Default: try automatic merge git merge-one-file "$filename" 2>/dev/null ;;esacEOF
chmod +x "$resolution_script"
if git merge-index "$resolution_script" -a; then echo "All conflicts resolved automatically" rm "$resolution_script" return 0 else echo "Some conflicts need manual resolution" echo "Leftover script: $resolution_script" return 1 fi}
auto_resolve_conflictsTroubleshooting Common Issues:
Section titled “Troubleshooting Common Issues:”Index State Problems:
Section titled “Index State Problems:”# Check index stategit statusgit ls-files --stage | grep -v "^100644 0"
# Reset problematic index entriesgit checkout --theirs conflicted-file.txtgit add conflicted-file.txt
# Verify index integritygit fsck --fullMerge Program Failures:
Section titled “Merge Program Failures:”# Test merge program manuallyecho "" | git-merge-one-file "" "" "" test.txt "" "" ""
# Debug merge programGIT_TRACE=1 git merge-index git-merge-one-file conflicted.txt
# Check merge program exit codesecho "Exit codes: 0=success, 1=conflict"Permission and Access Issues:
Section titled “Permission and Access Issues:”# Check file permissionsls -la conflicted-file.txtgit ls-files --stage conflicted-file.txt
# Fix permissionschmod 644 conflicted-file.txt
# Handle read-only fileschmod u+w conflicted-file.txtLarge File Merge Issues:
Section titled “Large File Merge Issues:”# Check file sizesgit ls-files --stage | awk '{print $4 ": " $3 " (" $1 " bytes)"}'
# Handle memory limitsulimit -v $((1024*1024*1024)) # 1GB memory limit
# Split large mergesgit merge-index git-merge-one-file -a --batch-size 10Real-World Usage Examples:
Section titled “Real-World Usage Examples:”Intelligent Conflict Resolution:
Section titled “Intelligent Conflict Resolution:”#!/bin/bash# Smart conflict resolution based on file analysis
SMART_RESOLVER=$(mktemp)cat > "$SMART_RESOLVER" << 'EOF'#!/bin/bashbase_sha=$1our_sha=$2their_sha=$3filename=$4
# Analyze what changedour_changes=$(git diff --no-index /dev/null <(git cat-file -p "$base_sha" 2>/dev/null || echo "") <(git cat-file -p "$our_sha") 2>/dev/null | wc -l || echo "0")their_changes=$(git diff --no-index /dev/null <(git cat-file -p "$base_sha" 2>/dev/null || echo "") <(git cat-file -p "$their_sha") 2>/dev/null | wc -l || echo "0")
echo "File: $filename"echo "Our changes: $our_changes lines"echo "Their changes: $their_changes lines"
# Resolution strategy based on change volumeif [ "$our_changes" -gt $((their_changes * 3)) ]; then echo "Taking our version (much larger changes)" git cat-file -p "$our_sha" > "$filename"elif [ "$their_changes" -gt $((our_changes * 3)) ]; then echo "Taking their version (much larger changes)" git cat-file -p "$their_sha" > "$filename"else # Similar change volume - need merge git merge-file "$filename" \ <(git cat-file -p "$base_sha" 2>/dev/null || echo "") \ <(git cat-file -p "$our_sha") \ <(git cat-file -p "$their_sha") echo "Attempted automatic merge"fiEOF
chmod +x "$SMART_RESOLVER"git merge-index "$SMART_RESOLVER" -arm "$SMART_RESOLVER"Merge Statistics and Reporting:
Section titled “Merge Statistics and Reporting:”#!/bin/bash# Generate merge operation statistics
generate_merge_report() { local report_file="merge-report-$(date +%Y%m%d-%H%M%S).txt"
echo "=== Git Merge Report $(date) ===" > "$report_file" echo "" >> "$report_file"
# Index state summary echo "Index State:" >> "$report_file" git ls-files --stage | awk ' /^100644 0/ {clean++} /^100644 [123]/ {conflict++} /^120000/ {symlink++} /^160000/ {submodule++} END { print "Clean files:", clean print "Conflicts:", conflict print "Symlinks:", symlink print "Submodules:", submodule } ' >> "$report_file" echo "" >> "$report_file"
# Per-file conflict details if git ls-files -u >/dev/null 2>&1; then echo "Files needing merge:" >> "$report_file" git ls-files -u | awk '{print $4}' | sort | uniq | \ while read file; do stages=$(git ls-files --stage "$file" | wc -l) echo " $file ($stages versions)" >> "$report_file" done echo "" >> "$report_file" fi
# Attempt automatic resolution echo "Automatic Resolution Attempt:" >> "$report_file"
MERGE_TRACKER=$(mktemp) cat > "$MERGE_TRACKER" << 'EOF'#!/bin/bashfilename=$4echo "Attempting: $filename"if git merge-one-file "$filename" 2>/dev/null; then echo "SUCCESS: $filename" >&2else echo "FAILED: $filename" >&2fiEOF chmod +x "$MERGE_TRACKER"
success_count=$(git merge-index "$MERGE_TRACKER" -a 2>&1 | grep -c "SUCCESS:") fail_count=$(git merge-index "$MERGE_TRACKER" -a 2>&1 | grep -c "FAILED:")
echo "Successfully resolved: $success_count" >> "$report_file" echo "Need manual resolution: $fail_count" >> "$report_file"
rm "$MERGE_TRACKER"
echo "Report saved to: $report_file" echo "Total conflicts resolved: $((success_count + fail_count))"}
generate_merge_reportEnterprise Merge Workflow:
Section titled “Enterprise Merge Workflow:”# Corporate merge validation and trackingcorporate_merge_workflow() { local ticket_id="$1" local change_description="$2"
echo "Starting corporate merge workflow" echo "Ticket: $ticket_id" echo "Description: $change_description"
# Pre-merge validation conflicted_files=$(git ls-files -u | wc -l) if [ "$conflicted_files" -gt 0 ]; then echo "Warning: $conflicted_files files already in conflicted state" return 1 fi
# Track merge operation start_time=$(date +%s)
MERGE_AUDITOR=$(mktemp) cat > "$MERGE_AUDITOR" << EOF#!/bin/bashfilename=\$4
# Log merge operationecho "\$(date): Merge operation on \$filename" >> merge-audit.logecho " Ticket: $ticket_id" >> merge-audit.logecho " User: \$(git config user.name) <\$(git config user.email)>" >> merge-audit.log
# Perform mergeif git merge-one-file "\$filename" 2>/dev/null; then echo " Status: AUTOMATIC" >> merge-audit.log echo "✓ \$filename merged automatically"else echo " Status: MANUAL_INTERVENTION_NEEDED" >> merge-audit.log echo "⚠ \$filename requires manual resolution" exit 1fiEOF
chmod +x "$MERGE_AUDITOR"
# Execute merge with auditing if git merge-index "$MERGE_AUDITOR" -a; then end_time=$(date +%s) duration=$((end_time - start_time))
echo "Merge completed successfully in ${duration}s" echo "Quality gate: PASSED"
# Create merge approval record git notes add -m "Corporate approval: $ticket_id" HEAD git notes append -m "Change: $change_description" HEAD git notes append -m "Duration: ${duration}s, Auto-resolved: 100%" HEAD
else echo "Merge requires manual intervention" echo "Quality gate: REVIEW_NEEDED" return 1 fi
rm "$MERGE_AUDITOR" echo "Audit log: merge-audit.log"}
# Usagecorporate_merge_workflow "PROJ-1234" "Feature implementation with security fixes"What’s the relationship between merge-index and git merge?
Section titled “What’s the relationship between merge-index and git merge?”git merge uses merge-index internally to process conflicted files. merge-index is the plumbing command, git merge is the porcelain interface.
How do I create custom merge programs for merge-index?
Section titled “How do I create custom merge programs for merge-index?”Write scripts that accept 7 arguments: base-sha, our-sha, their-sha, filename, base-mode, our-mode, their-mode. Return 0 for success, non-zero for conflict.
What does the -o option do in merge-index?
Section titled “What does the -o option do in merge-index?”Skips checking if files actually need merging. Useful for testing merge programs on all files, regardless of conflict state.
Can merge-index work with binary files?
Section titled “Can merge-index work with binary files?”Yes, but merge programs must handle binary content appropriately. Standard merge programs are text-oriented.
How do I debug merge-index operations?
Section titled “How do I debug merge-index operations?”Use GIT_TRACE=1 to see detailed execution. Test merge programs independently before using with merge-index.
What’s the difference between git merge-index and git merge-one-file?
Section titled “What’s the difference between git merge-index and git merge-one-file?”merge-index orchestrates merges across multiple files using your specified program; merge-one-file is a specific program that merge-index can use.
Can merge-index process files in parallel?
Section titled “Can merge-index process files in parallel?”Use —parallel option or external parallelization. File dependencies may limit parallelism effectiveness.
How do I handle merge-index timeouts?
Section titled “How do I handle merge-index timeouts?”Use timeout command: timeout 300 git merge-index merge-program -a. Individual merge operations may need per-file timeouts.
What happens if a merge program crashes during merge-index?
Section titled “What happens if a merge program crashes during merge-index?”Remaining files continue processing. Use -q to suppress error output. Failed merges remain unresolved in index.
Can merge-index work in bare repositories?
Section titled “Can merge-index work in bare repositories?”Yes, operates on index regardless of working directory. Useful for server-side merge validation.
Applications of the git merge-index command
Section titled “Applications of the git merge-index command”- Automated Merge Processing: Run custom merge logic during Git merge operations
- Conflict Resolution Automation: Implement intelligent conflict resolution based on file types and content
- Merge Validation: Test merge viability before committing changes
- Custom Merge Drivers: Support specialized merge strategies for different file types
- Enterprise Merge Auditing: Track and audit merge operations in corporate workflows
- Bulk Merge Operations: Process large numbers of merge conflicts systematically