Skip to content

merge-file Git Command Guide

The git merge-file command performs three-way file merging, combining changes from two modified versions of a file into a single result. It takes three files (current, base, other) and merges changes from base→other into current, handling conflicts with standard conflict markers.

Terminal window
git merge-file [-L <current-name> [-L <base-name> [-L <other-name>]]]
[--ours|--theirs|--union] [-p|--stdout] [-q|--quiet] [--marker-size=<n>]
[--[no-]diff3] [--object-id] <current> <base> <other>
OptionDescription
--oursChoose our version on conflicts
--theirsChoose their version on conflicts
--unionCombine both versions on conflicts
OptionDescription
-p, --stdoutSend output to stdout instead of overwriting file
-q, --quietSuppress conflict warnings
--marker-size=<n>Change conflict marker size
OptionDescription
-L <label>Use custom label for conflict markers
OptionDescription
--diff3Use diff3-style conflict markers
--no-diff3Use standard conflict markers
--object-idAdd object IDs to conflict markers
ParameterDescription
<current>Current version of the file (will be modified)
<base>Common ancestor/base version
<other>Other version to merge in
Terminal window
# Merge changes from other into current using base as reference
git merge-file current.txt base.txt other.txt
# Merge with custom output (don't modify current file)
git merge-file -p current.txt base.txt other.txt > merged.txt
Terminal window
# Always prefer current version on conflicts
git merge-file --ours current.txt base.txt other.txt
# Always prefer other version on conflicts
git merge-file --theirs current.txt base.txt other.txt
# Combine both versions on conflicts
git merge-file --union current.txt base.txt other.txt
Terminal window
# Use descriptive labels instead of filenames
git merge-file -L current -L base -L other current.txt base.txt other.txt
# Name versions for easier conflict resolution
git merge-file -L "My changes" -L "Common base" -L "Their changes" file.txt base.txt their.txt
Original (base) Modified A (other)
| |
| | git merge-file merges changes
| | A->base into current file
v v
Current (our version) <-- merges to --> Result
<<<<<<< current.txt
Line from current file
Change made in our branch
Line from other file
Change made in their branch
>>>>>>> other.txt
<<<<<<< current.txt
our line
||||||| base.txt
original line
their line
>>>>>>> other.txt
#!/bin/bash
# Resolve merge conflicts using merge-file
resolve_conflict() {
local conflicted_file="$1"
local base_commit="${2:-HEAD~1}" # Merge base
local our_commit="${3:-HEAD}"
local their_commit="${4:-MERGE_HEAD}"
# Create temporary versions
git show "$base_commit:$conflicted_file" > .base.tmp
git show "$our_commit:$conflicted_file" > .ours.tmp
git show "$their_commit:$conflicted_file" > .theirs.tmp
# Perform three-way merge
if git merge-file -p .ours.tmp .base.tmp .theirs.tmp > "$conflicted_file"; then
echo "✓ Auto-merged $conflicted_file"
# Clean up
rm .base.tmp .ours.tmp .theirs.tmp
git add "$conflicted_file"
else
echo "Conflicts remain in $conflicted_file"
echo "Edit $conflicted_file and run 'git add $conflicted_file'"
# Leave temporary files for manual resolution
fi
}
# Usage
resolve_conflict "conflicted-file.txt"

Patch Application with Conflict Detection:

Section titled “Patch Application with Conflict Detection:”
Terminal window
# Test if patch can be applied cleanly
apply_with_merge() {
local patch_file="$1"
local target_file="$2"
# Backup original
cp "$target_file" "${target_file}.backup"
# Get base version (unpatched)
# This would need to be implemented based on patch format
# Apply changes using merge-file
git merge-file "$target_file" base.txt patched.txt
}
# Example workflow for patch testing
# (Assumes base.txt exists as unpatched version)
# git merge-file --stdout current.txt base.txt patched.txt | patch --dry-run
Terminal window
# Test how branches would merge without committing
test_branch_merge() {
local feature_branch="$1"
local target_branch="${2:-main}"
# Get merge base
base_commit=$(git merge-base "$target_branch" "$feature_branch")
# Test merge for each conflicting file
git diff --name-only "$base_commit" "$target_branch" "$feature_branch" | while read file; do
echo "Testing merge of $file"
# Create temporary versions
git show "$base_commit:$file" > .base.tmp
git show "$target_branch:$file" > .target.tmp
git show "$feature_branch:$file" > .feature.tmp
# Try merge
if git merge-file -q .target.tmp .base.tmp .feature.tmp; then
echo "$file merges cleanly"
else
echo "$file has conflicts"
fi
rm .base.tmp .target.tmp .feature.tmp
done
}
# Usage
test_branch_merge "feature-x" "main"
Terminal window
# Configure default conflict style
git config merge.conflictStyle diff3
git config merge.conflictStyle merge # Standard style
# Configure merge-file to use diff3 style
# Handled via command-line --diff3 option
#!/bin/bash
# Enhanced merge with backup and logging
enhanced_merge() {
local current="$1"
local base="$2"
local other="$3"
local output="${4:-${current}}"
echo "Merging $current with $base and $other"
# Backup if output would overwrite
if [ "$output" = "$current" ]; then
cp "$current" "${current}.backup.$(date +%s)"
fi
# Perform merge with logging
if git merge-file -p "$current" "$base" "$other" > "$output" 2>merge.log; then
echo "✓ Merge successful"
[ -f merge.log ] && rm merge.log
else
echo "⚠ Merge completed with conflicts"
echo "Resolve conflicts in $output"
echo "See merge.log for details"
# Create markers for manual resolution
echo "Merge details:" >> merge.log
echo "Current: $current" >> merge.log
echo "Base: $base" >> merge.log
echo "Other: $other" >> merge.log
fi
}
# Usage
enhanced_merge file.txt base.txt their.txt merged.txt
Terminal window
# Merge review changes with automatic conflict resolution
merge_review_changes() {
local original_file="$1"
local review_comments="$2"
cp "$original_file" "${original_file}.base"
# Apply review changes (this would be automated based on review system)
# For demo, assume review_comments contains change instructions
# Use merge-file to combine automatic application with review changes
git merge-file "$original_file" "${original_file}.base" "$review_comments"
if [ $? -eq 0 ]; then
echo "Review changes applied successfully"
else
echo "Manual review of $original_file needed"
fi
rm "${original_file}.base"
}
Terminal window
# Migrate files between repositories with conflict resolution
migrate_with_merge() {
local old_repo_file="$1"
local new_repo_file="$2"
# Find common ancestor (might be git log analysis)
# This is simplified - real migration would need history analysis
git merge-file "$old_repo_file" /dev/null "$new_repo_file"
if [ $? -eq 0 ]; then
echo "Files migrated successfully"
git add "$old_repo_file"
else
echo "Manual conflict resolution needed in $old_repo_file"
fi
}
Terminal window
# Check if files exist and are readable
ls -la current.txt base.txt other.txt
# Ensure files are not empty
[ -s current.txt ] && echo "current.txt is OK" || echo "current.txt is empty"
# Check for binary files (merge-file works on text)
file current.txt base.txt other.txt
Terminal window
# Ensure consistent encoding
file current.txt base.txt other.txt
# Convert encoding if needed
iconv -f latin1 -t utf8 current.txt > current_utf8.txt
git merge-file current_utf8.txt base.txt other.txt
mv current_utf8.txt current.txt
Terminal window
# Ensure proper permissions
chmod 644 current.txt base.txt other.txt
ls -la current.txt base.txt other.txt
# Check filesystem space
df -h .
Terminal window
# For large files, check memory
ulimit -v
free -h
# Split large files if needed
split -l 10000 large-file.txt large-file.part.
git merge-file large-file.part.aa base.txt other.txt
cat large-file.part.a* > merged-large-file.txt
Terminal window
# When a fork has diverged significantly
resolve_fork_conflicts() {
local upstream_repo="$1"
local local_file="$2"
# Get upstream version
git show "$upstream_repo/$(basename "$local_file")" > upstream.tmp
# Get common ancestor commit
base_commit=$(git merge-base HEAD "$upstream_repo" 2>/dev/null || git log --oneline -1 | awk '{print $1}')
git show "$base_commit:$local_file" > base.tmp
# Merge changes
if git merge-file "$local_file" base.tmp upstream.tmp; then
echo "✓ Successfully merged $local_file changes from upstream"
git add "$local_file"
else
echo "Conflicts in $local_file need manual resolution"
fi
rm upstream.tmp base.tmp
}
# Usage for repository sync
resolve_fork_conflicts "origin/main" "important-file.txt"
Terminal window
# Merge feature branches with conflict resolution
merge_feature_branches() {
local branch1="$1"
local branch2="$2"
local target_file="$3"
# Create temporary working copies
git show "$branch1:$target_file" > branch1.tmp
git show "$branch2:$target_file" > branch2.tmp
# Find common ancestor
base_commit=$(git merge-base "$branch1" "$branch2")
git show "$base_commit:$target_file" > base.tmp
# Attempt automatic merge
if git merge-file --ours branch1.tmp base.tmp branch2.tmp; then
mv branch1.tmp "$target_file"
echo "✓ Features merged automatically"
else
echo "Manual merge needed for $target_file"
# Leave temporary files for inspection
echo "Compare: base.tmp, branch1.tmp, branch2.tmp"
echo "Edit: $target_file"
return 1
fi
rm base.tmp branch1.tmp branch2.tmp
}
# Usage
merge_feature_branches "feature-a" "feature-b" "shared-code.py"
Terminal window
# Manage configuration files across environments
merge_configurations() {
local dev_config="$1"
local prod_config="$2"
local staging_config="$3"
# Create base from initial config
git show HEAD~10:"$(basename "$dev_config")" > base-config.tmp
# Merge dev changes into staging
git merge-file "$staging_config" base-config.tmp "$dev_config"
if [ $? -eq 0 ]; then
echo "✓ Dev changes merged into staging"
git add "$staging_config"
else
echo "Review $staging_config for environment-specific settings"
echo "Dev changes may need adaptation for staging"
fi
# Also merge into production with cautions
git merge-file --stdout "$prod_config" base-config.tmp "$dev_config" > prod-preview.tmp
echo "Preview merged production config in prod-preview.tmp"
rm base-config.tmp prod-preview.tmp
}
# Usage for config deployment
merge_configurations "config.dev.yml" "config.prod.yml" "config.staging.yml"

What’s the difference between git merge-file and regular file concatenation?

Section titled “What’s the difference between git merge-file and regular file concatenation?”

git merge-file performs intelligent three-way merging, identifying conflicts and preserving separate changes, while concatenation simply appends files.

How do I handle binary files with merge-file?

Section titled “How do I handle binary files with merge-file?”

merge-file is designed for text files. Use git merge for files tracked in Git, or alternative tools for binary file merge operations.

Can merge-file be used outside of Git repositories?

Section titled “Can merge-file be used outside of Git repositories?”

Yes, git merge-file is a standalone utility. It doesn’t require a Git repository and can merge any three text files.

What’s the relationship between merge-file and git merge?

Section titled “What’s the relationship between merge-file and git merge?”

git merge calls git merge-file (via git merge-index) on conflicted files. merge-file is the low-level utility, git merge provides high-level workflow.

How do I automate conflict resolution with merge-file?

Section titled “How do I automate conflict resolution with merge-file?”

Use —ours or —theirs for automatic resolution strategies, or interpret conflict markers in scripts to apply intelligent resolution logic.

Can merge-file merge multiple files at once?

Section titled “Can merge-file merge multiple files at once?”

No, processes one file at a time. Use shell loops or build scripts to merge multiple file sets.

Controls length of conflict markers (<<<<<<< ======= >>>>>>>). Useful for files with similar content where short markers might appear naturally.

How do I handle different line endings with merge-file?

Section titled “How do I handle different line endings with merge-file?”

Generally handles line ending differences automatically. Use dos2unix/unix2dos if needed before merging for complex mixed line ending scenarios.

Yes, supports UTF-8 and other Unicode encodings. Ensure consistent encoding between all three input files.

Adds Git object IDs to conflict markers for integration with Git’s conflict resolution, showing where each version came from in the repository.

How do I use merge-file in pre-commit hooks?

Section titled “How do I use merge-file in pre-commit hooks?”

Test merge conflicts before committing by merging with branch bases, or validate file integrity changes.

No, operates on file content only. Use git merge for complete file lifecycle including renames and permission changes.

What’s the performance impact of large file merging?

Section titled “What’s the performance impact of large file merging?”

Linear with file size. Memory usage scales with file size and number of conflicts. Use system limits for very large files.

Applications of the git merge-file command

Section titled “Applications of the git merge-file command”
  1. Merge Conflict Resolution: Manually resolve Git merge conflicts with three-way diff visualization
  2. Automated File Merging: Script-based merging of configuration files across environments
  3. Version Control Migration: Migrate files between repositories with conflict detection
  4. Collaborative Document Editing: Merge changes from multiple contributors working on documents
  5. Configuration Management: Merge configuration changes across development, staging, and production
  6. Patch Testing and Validation: Test patch applicability before application with conflict detection