merge-base Git Command Guide
The git merge-base command finds the best common ancestor(s) between two or more commits to use in a three-way merge. It identifies the most appropriate merge base for resolving conflicts and understanding development history relationships.
git merge-base Syntax:
Section titled “git merge-base Syntax:”git merge-base [-a | --all] <commit> <commit>...git merge-base [-a | --all] --octopus <commit>...git merge-base --is-ancestor <commit> <commit>git merge-base --independent <commit>...git merge-base --fork-point <ref> [<commit>]Operation Modes:
Section titled “Operation Modes:”Basic Merge Base Calculation:
Section titled “Basic Merge Base Calculation:”| Mode | Description |
|---|---|
<commit> <commit> | Find best common ancestor between two commits |
--all | Show all merge bases, not just the best one |
--octopus | Compute merge base for octopus merge (multiple branches) |
Relationship Testing:
Section titled “Relationship Testing:”| Mode | Description |
|---|---|
--is-ancestor <commit> <commit> | Test if first commit is ancestor of second |
--independent <commit>... | Find minimal set of commits with no common ancestors |
--fork-point <ref> [<commit>] | Find commit where branch forked from reference |
Parameters:
Section titled “Parameters:”| Parameter | Description |
|---|---|
<commit> | Commit SHA, branch name, or tag reference |
<ref> | Reference point (usually branch or remote) |
Basic Merge Base Examples:
Section titled “Basic Merge Base Examples:”Two-Commit Merge Base:
Section titled “Two-Commit Merge Base:”# Find merge base between two commitsgit merge-base main feature-branch
# Find merge base between HEAD and specific commitgit merge-base HEAD abc123
# Find merge base between two branch refsgit merge-base origin/main developMultiple Merge Bases:
Section titled “Multiple Merge Bases:”# Show all merge bases (not just best one)git merge-base --all main feature1 feature2
# Octopus merge base for three branchesgit merge-base --octopus main feature1 feature2 feature3Relationship Testing:
Section titled “Relationship Testing:”# Test if commit is ancestor of anothergit merge-base --is-ancestor main HEAD && echo "main is ancestor"
# Find independent commits (no common ancestors)git merge-base --independent HEAD~5 HEAD~3 HEAD~1Fork Point Detection:
Section titled “Fork Point Detection:”# Find where current branch forked from maingit merge-base --fork-point main
# Find fork point for specific branchgit merge-base --fork-point main feature-branchAdvanced Merge Base Scenarios:
Section titled “Advanced Merge Base Scenarios:”Complex Branch Structures:
Section titled “Complex Branch Structures:”# Diamond merge patterngit merge-base HEAD^1 HEAD^2 # Find base of merge commit
# Cross-branch comparisongit merge-base release/v1 release/v2
# Release branching strategygit merge-base --all develop release/v1 release/v2Conflict Resolution Preparation:
Section titled “Conflict Resolution Preparation:”# Before merging, find appropriate merge baseBASE=$(git merge-base HEAD MERGE_HEAD)echo "Using merge base: $BASE"
# Check what files changed since merge basegit diff --name-only $BASE
# Three-way diff for conflict analysisgit diff $BASE HEAD MERGE_HEAD -- file-with-conflict.txtRelease Management:
Section titled “Release Management:”# Find common base between two releasesgit merge-base --all v1.0 v2.0
# Determine hotfix merge strategyHOTFIX_BASE=$(git merge-base production hotfix-123)git log $HOTFIX_BASE..hotfix-123 # Changes in hotfixIntegration with Git Workflows:
Section titled “Integration with Git Workflows:”Automated Merge Strategy Selection:
Section titled “Automated Merge Strategy Selection:”#!/bin/bash# Determine appropriate merge strategy
source_branch="$1"target_branch="${2:-main}"
# Find merge basemerge_base=$(git merge-base "$target_branch" "$source_branch")
if [ $? -ne 0 ]; then echo "Branches have no common history - force merge required" exit 1fi
# Check if fast-forward is possibleif git merge-base --is-ancestor "$source_branch" "$target_branch"; then echo "Fast-forward merge possible" git merge --ff-only "$source_branch"elif git merge-base --is-ancestor "$target_branch" "$source_branch"; then echo "Already up to date" exit 0else echo "Three-way merge required with base: $merge_base" git merge --no-ff "$source_branch"fiBranch Relationship Analysis:
Section titled “Branch Relationship Analysis:”# Analyze branch relationships in repositoryanalyze_branches() { local branch1="$1" local branch2="$2"
merge_base=$(git merge-base "$branch1" "$branch2" 2>/dev/null)
if [ $? -eq 0 ]; then echo "=== Branch Analysis: $branch1 vs $branch2 ===" echo "Merge base: $merge_base"
# Check relationships if git merge-base --is-ancestor "$merge_base" "$branch1" 2>/dev/null; then echo "$branch1 contains merge base" fi
if git merge-base --is-ancestor "$merge_base" "$branch2" 2>/dev/null; then echo "$branch2 contains merge base" fi
# Count commits from merge base commits1=$(git rev-list --count "$merge_base..$branch1") commits2=$(git rev-list --count "$merge_base..$branch2")
echo "Commits since merge-base:" echo " $branch1: $commits1" echo " $branch2: $commits2"
# Divergence analysis if [ "$commits1" -eq 0 ] && [ "$commits2" -eq 0 ]; then echo "Branches are identical" elif [ "$commits1" -eq 0 ]; then echo "$branch1 can fast-forward to $branch2" elif [ "$commits2" -eq 0 ]; then echo "$branch2 can fast-forward to $branch1" else echo "Branches have diverged - $((commits1 + commits2)) total commits" fi else echo "Branches have no common history" fi}
# Usageanalyze_branches main feature-xanalyze_branches develop release/v1CI/CD Pipeline Integration:
Section titled “CI/CD Pipeline Integration:”# Pre-merge validation in CIvalidate_merge() { local source_commit="$1" local target_branch="$2"
# Find merge base merge_base=$(git merge-base "$target_branch" "$source_commit")
if [ $? -ne 0 ]; then echo "ERROR: No common history - merge not possible" exit 1 fi
echo "Merge base: $merge_base"
# Test merge without committing if git merge-tree "$merge_base" "$target_branch" "$source_commit" >/dev/null 2>&1; then echo "✓ Clean merge possible" return 0 else echo "⚠ Conflicts detected - manual resolution needed"
# Show conflicting files git merge-tree "$merge_base" "$target_branch" "$source_commit" | grep "^<<<<<<<\|^=======\|^>>>>>>>" -B1 -A1 | head -10
return 1 fi}
# Usage in CIif validate_merge "${CI_MERGE_REQUEST_TARGET_BRANCH}" "${CI_COMMIT_SHA}"; then echo "Merge validation passed"else echo "Merge validation failed" exit 1fiUnderstanding Merge Base Concepts:
Section titled “Understanding Merge Base Concepts:”Best Common Ancestor:
Section titled “Best Common Ancestor:”A - B - C (main branch) \ D - E (feature branch)
Merge base: B (best common ancestor)Multiple Merge Bases (Criss-Cross):
Section titled “Multiple Merge Bases (Criss-Cross):”A - B - E - F| \ /| X| / \C - D - Y - G
Merge bases: [B, D] (both are equally good)Use --all to see all merge basesOctopus Merges:
Section titled “Octopus Merges:” H (merge commit) /|\ C -- D | F -- G / | \A -- B E I | J -- K
Merge base: A (common ancestor for 3-way octopus merge)Troubleshooting Common Scenarios:
Section titled “Troubleshooting Common Scenarios:”No Merge Base Found:
Section titled “No Merge Base Found:”# Check repository stategit log --oneline --all --graph | head -20
# Verify commit existsgit cat-file -t "$COMMIT_HASH"
# Check for disconnected historiesgit log --oneline "$BRANCH1" "$BRANCH2" --not $(git merge-base --all "$BRANCH1" "$BRANCH2") | head -5Multiple Merge Bases:
Section titled “Multiple Merge Bases:”# Show all merge basesgit merge-base --all branch1 branch2
# Choose appropriate one based on context# Usually the oldest (first) one is preferredbases=( $(git merge-base --all branch1 branch2) )echo "Best merge base: ${bases[0]}"Fork Point Issues:
Section titled “Fork Point Issues:”# Debug fork point detectiongit log --oneline --decorate --graph --all | grep -A5 -B5 "$(git merge-base --fork-point main)"
# Manual fork point identificationgit log --oneline main..feature | tail -1Performance Issues:
Section titled “Performance Issues:”# Cache merge-base results for repeated operationsMERGE_BASE_CACHE="/tmp/merge-base-$RANDOM"git merge-base main feature > "$MERGE_BASE_CACHE"
# Use cached resultbase_commit=$(cat "$MERGE_BASE_CACHE")Real-World Usage Examples:
Section titled “Real-World Usage Examples:”Git Merge Conflict Resolution:
Section titled “Git Merge Conflict Resolution:”# Before merge, understand conflict sourcesCONFLICT_BASE=$(git merge-base HEAD MERGE_HEAD)echo "Conflicts originate from changes after: $CONFLICT_BASE"
# Show what changed in each branchgit log --oneline $CONFLICT_BASE..HEAD | head -5 # Our changesgit log --oneline $CONFLICT_BASE..MERGE_HEAD | head -5 # Their changes
# Analyze specific file conflictgit diff $CONFLICT_BASE HEAD -- conflicted-file.txt # Our changesgit diff $CONFLICT_BASE MERGE_HEAD -- conflicted-file.txt # Their changesRebase Strategy Planning:
Section titled “Rebase Strategy Planning:”# Determine if rebase or merge strategy is bettersource_branch="feature-abc"target_branch="main"
base=$(git merge-base "$target_branch" "$source_branch")source_commits=$(git rev-list --count "$base..$source_branch")target_commits=$(git rev-list --count "$base..$target_branch")
if [ "$target_commits" -gt 0 ]; then echo "Branches diverged - consider merge instead of rebase" echo "Rebase would create $target_commits merge commits"else echo "Rebase safe - no divergence detected" git rebase "$target_branch" "$source_branch"fiAutomated Patch Management:
Section titled “Automated Patch Management:”#!/bin/bash# Manage patch series with merge-base tracking
# Track patch application statusfind patches/ -name "*.patch" | while read patch_file; do patch_id=$(basename "$patch_file" .patch)
# Check if patch is already applied if git log --grep="$patch_id" --oneline >/dev/null; then echo "✓ Patch $patch_id already applied" continue fi
# Test patch application if git apply --check "$patch_file" 2>/dev/null; then echo "Applying patch: $patch_id" git am "$patch_file"
# Record merge-base for future reference applied_base=$(git merge-base HEAD HEAD~1) git notes add -m "Patch: $patch_id, Base: $applied_base" HEAD else echo "✗ Patch $patch_id has conflicts - manual intervention needed" fidoneHow merge-base handles criss-cross merges?
Section titled “How merge-base handles criss-cross merges?”Returns all equally good merge bases with —all option. Algorithm finds minimal set of commits with no better common ancestors available.
What’s the difference between merge-base and git log —merges?
Section titled “What’s the difference between merge-base and git log —merges?”git log —merges shows merge commits; git merge-base finds the common ancestor commit used for creating those merges, enabling analysis before merging.
Can merge-base work with tags and remotes?
Section titled “Can merge-base work with tags and remotes?”Fully supports refs: git merge-base v1.0 v2.0, git merge-base origin/main HEAD. Works with any commit-ish reference in Git.
How do I find the merge-base of an octopus merge?
Section titled “How do I find the merge-base of an octopus merge?”Use git merge-base —octopus branch1 branch2 branch3 when more than two branches converge, calculating the common ancestor for complex multi-branch scenarios.
What’s the performance impact of merge-base?
Section titled “What’s the performance impact of merge-base?”Very fast operation - traverses commit graph similar to git log —graph. Performance scales with repository depth, typically sub-second for reasonable history sizes.
Can merge-base detect if branches have diverged?
Section titled “Can merge-base detect if branches have diverged?”Yes, compare results: same merge-base means branches haven’t diverged. Different commits from merge-base indicate divergence requiring merge resolution.
How do I use merge-base with git rebase?
Section titled “How do I use merge-base with git rebase?”Pre-rebase analysis: git merge-base topic main shows what commits will be replayed. Post-rebase verification ensures rebase maintains correct history relationships.
What’s the relationship between merge-base and three-way diff?
Section titled “What’s the relationship between merge-base and three-way diff?”Git uses merge-base as third point in three-way diff/merge: git diff BASE HEAD MERGE_HEAD shows changes from common ancestor to each branch tip.
Can merge-base work with rewritten history?
Section titled “Can merge-base work with rewritten history?”Works with current commit graph. After rebase, merge bases change because commit relationships change. Use git merge-base —fork-point to find original branch point in rewritten history.
How do I handle multiple merge-bases in scripts?
Section titled “How do I handle multiple merge-bases in scripts?”Use git merge-base —all and select first result (—all output is ordered by preference). For automation, first merge-base is usually most appropriate.
What’s the difference between git merge-base and git show-branch —merge-base?
Section titled “What’s the difference between git merge-base and git show-branch —merge-base?”git show-branch —merge-base shows merge base for current branches; git merge-base provides programmatic interface for any commits and more advanced options like —octopus.
Applications of the git merge-base command
Section titled “Applications of the git merge-base command”- Merge Conflict Analysis: Understand conflict origins by identifying common ancestor and branch changes
- Branch Relationship Analysis: Determine how branches relate and what merging strategy to use
- Automated Merge Decision Making: Enable scripts to choose fast-forward vs three-way merge strategies
- Release Management: Track where releases branched from and what changes they contain
- Conflict Prevention: Test potential merges before execution using merge-tree with merge-base
- Development Workflow Optimization: Automate rebase vs merge decisions based on branch divergence