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
- Fast-forward: Target branch has no new commits.
- Three-way merge: Both branches have new commits.
- 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-loginOutput:
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.jsFeatures 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 possibleThree-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-registerGit automatically creates a merge commit:
Merge made by the 'recursive' strategy.
register.js | 1 +
1 file changed, 1 insertion(+)
create mode 100644 register.jsCustom 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 --editMerge 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 changesOctopus Strategy
For merging multiple branches:
bash
# Merge multiple branches at once
git merge branch1 branch2 branch3Ours Strategy
Keep current branch content, ignore other branch changes:
bash
# Use ours strategy
git merge -s ours feature/branch-nameSubtree Strategy
For subtree merging:
bash
# Subtree merge
git merge -s subtree feature/branch-nameHandling 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-updateConflict Output:
Auto-merging config.txt
CONFLICT (add/add): Merge conflict in config.txt
Automatic merge failed; fix conflicts and then commit the result.