Skip to content

Git Merge

Merging is a core operation in Git to integrate changes from different branches. This chapter details various merge strategies, conflict resolution, and best practices.

Basic Merge Concepts

What is a Merge?

Merging is the process of integrating changes from one branch into another. Git provides multiple merge strategies for different scenarios.

Before Merge:
A---B---C  (main)
     \
      D---E  (feature)

After Merge:
A---B---C---F  (main)
     \     /
      D---E    (feature)

Merge Types

  1. Fast-forward: Target branch has no new commits.
  2. Three-way merge: Both branches have new commits.
  3. Squash merge: Compress multiple commits into one.

Basic Merge Operations

Prepare Demo Environment

bash
# Create demo project
mkdir git-merge-demo
cd git-merge-demo
git init

# Create initial commit
echo "# Merge Demo Project" > README.md
git add README.md
git commit -m "Initial commit"

# Create and switch to feature branch
git checkout -b feature/user-login
echo "Login feature" > login.js
git add login.js
git commit -m "Add login feature"

echo "Login style" > login.css
git add login.css
git commit -m "Add login style"

Fast-forward Merge

When the target branch (usually main) has no new commits, Git performs a fast-forward merge:

bash
# Switch back to main branch
git checkout main

# Perform fast-forward merge
git merge feature/user-login

Output:

Updating a1b2c3d..e4f5g6h
Fast-forward
 login.css | 1 +
 login.js  | 1 +
 2 files changed, 2 insertions(+)
 create mode 100644 login.css
 create mode 100644 login.js

Features of Fast-forward:

  • No new merge commit created
  • History remains linear
  • Branch pointer moves directly

Disable Fast-forward

bash
# Force create merge commit
git merge --no-ff feature/user-login

# This creates a merge commit even if fast-forward is possible

Three-way Merge

Create Three-way Merge Scenario

bash
# Add commit on main branch
git checkout main
echo "Main branch update" >> README.md
git add README.md
git commit -m "Update README"

# Create new feature branch
git checkout -b feature/user-register
echo "Register feature" > register.js
git add register.js
git commit -m "Add register feature"

# Switch back to main and merge
git checkout main
git merge feature/user-register

Git automatically creates a merge commit:

Merge made by the 'recursive' strategy.
 register.js | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 register.js

Custom Merge Commit Message

bash
# Specify commit message during merge
git merge feature/user-register -m "Merge user register feature"

# Edit commit message during merge
git merge feature/user-register --edit

Merge Strategies

Recursive Strategy

The default strategy for most cases:

bash
# Explicitly specify recursive strategy
git merge -s recursive feature/branch-name

# Options for recursive strategy
git merge -s recursive -X ours feature/branch-name      # Prefer current branch on conflict
git merge -s recursive -X theirs feature/branch-name    # Prefer merge branch on conflict
git merge -s recursive -X ignore-space-change feature/branch-name  # Ignore whitespace changes

Octopus Strategy

For merging multiple branches:

bash
# Merge multiple branches at once
git merge branch1 branch2 branch3

Ours Strategy

Keep current branch content, ignore other branch changes:

bash
# Use ours strategy
git merge -s ours feature/branch-name

Subtree Strategy

For subtree merging:

bash
# Subtree merge
git merge -s subtree feature/branch-name

Handling Merge Conflicts

Identifying Conflicts

Conflicts occur when two branches modify the same part of the same file:

bash
# Create conflict scenario
git checkout main
echo "Main branch config" > config.txt
git add config.txt
git commit -m "Add main branch config"

git checkout -b feature/config-update
echo "Feature branch config" > config.txt
git add config.txt
git commit -m "Update config file"

# Try to merge (will conflict)
git checkout main
git merge feature/config-update

Conflict Output:

Auto-merging config.txt
CONFLICT (add/add): Merge conflict in config.txt
Automatic merge failed; fix conflicts and then commit the result.

Content is for learning and research only.