A Detailed Guide to Git Merging and Conflict Resolution

A merge is the process of combining changes from different branches. Through merging, teams can develop different features in parallel and then integrate them into a single version. Understanding the principles of merging and conflict resolution is crucial for team collaboration.

1. Basic Concepts of Mergers

(1) What Is a Merger?

A merge is the process of applying changes from one branch to another. Git attempts to merge the changes automatically, but conflicts may arise when changes on the two branches affect the same location.

100%
graph TB
    A[mainBranch] --> B[MergefeatureBranch]
    B --> C{Is there a conflict??}
    C -->|No conflict| D[Automatic merge successful]
    C -->|There is a conflict| E[Resolve conflicts manually]
    E --> F[Mark the conflict as resolved]
    F --> G[Complete the merger]
    
    style D fill:#d4edda
    style E fill:#fff3cd

(2) Types of Mergers

Git supports two types of merges:

(3) Direction of the Merge

TEXT
git merge feature  # Merge feature into the current branch

A merge always merges the specified branch into the current branch, so be sure to check the current branch before merging.


2. Fast-forward merge

(1) The Principle of Fast-Forward Merging

When the target branch (such as main) has no new commits, but the branch to be merged (such as feature) has new commits, Git can simply move the main pointer forward; this is called a fast-forward merge.

100%
graph LR
    subgraph Before the merger
        C1[SubmitC1] --> C2[SubmitC2]
        C2 --> C3[SubmitC3]
        main1[main] --> C2
        feature1[feature] --> C3
    end
    
    subgraph After the merger
        C4[SubmitC1] --> C5[SubmitC2]
        C5 --> C6[SubmitC3]
        main2[main] --> C6
        feature2[feature] --> C6
    end
    
    style main1 fill:#fff3cd
    style main2 fill:#d4edda

(2) Perform a fast-forward merge

▶ Example: Fast-forward merge

BASH
# View Current Status
git log --oneline --graph --all

# Output:
# * d4e5f6g (feature) Add feature
# * a1b2c3d (HEAD -> main) Initial commit

# Switch tomainBranch
git switch main

# MergefeatureBranch
git merge feature

# Output:
# Updating a1b2c3d..d4e5f6g
# Fast-forward
#  feature.js | 1 +
#  1 file changed, 1 insertion(+)
#  create mode 100644 feature.js

# View the merge results
git log --oneline --graph --all

# Output:
# * d4e5f6g (HEAD -> main, feature) Add feature
# * a1b2c3d Initial commit

(3) Disable fast-forward merge

Sometimes, even when fast-forward merges are possible, I want to create a merge commit to preserve the branch history.

▶ Example: Disabling Fast-Forward Merge

BASH
# Usage--no-ffDisable Fast-Forward Merge
git merge --no-ff feature

# Output:
# Merge made by the 'ort' recursive strategy.
#  feature.js | 1 +
#  1 file changed, 1 insertion(+)
#  create mode 100644 feature.js

# View History
git log --oneline --graph --all

# Output:
# *   a1b2c3d (HEAD -> main) Merge branch 'feature'
# |\
# | * d4e5f6g (feature) Add feature
# |/
# * h7i8j9k Initial commit

3. Three-Party Merger

(1) The Principle of Three-Way Merging

When both branches have new commits, Git needs to find a common ancestor (the merge base) and then perform a three-way merge.

100%
graph TB
    A[Common Ancestor<br/>Merged Base] --> B[mainBranch Commit]
    A --> C[featureBranch Commit]
    B --> D[Three-Party Merger]
    C --> D
    D --> E[Merge Commit]
    
    style A fill:#fff3cd
    style E fill:#d4edda

(2) Execute a three-party merger

▶ Example: Three-Party Merger

BASH
# View Branch Status
git log --oneline --graph --all

# Output:
# * d4e5f6g (feature) Feature work
# | * a1b2c3d (HEAD -> main) Main work
# |/
# * h7i8j9k Initial commit

# MergefeatureBranch
git merge feature

# Output:
# Merge made by the 'ort' recursive strategy.
#  feature.js | 1 +
#  1 file changed, 1 insertion(+)

# View the merge results
git log --oneline --graph --all

# Output:
# *   k9l0m1n (HEAD -> main) Merge branch 'feature'
# |\
# | * d4e5f6g (feature) Feature work
# * | a1b2c3d Main work
# |/
# * h7i8j9k Initial commit

(3) View the merge base

▶ Example: Finding a Common Ancestor

BASH
# Find the common ancestor of two branches
git merge-base main feature

# Output:
# h7i8j9k

# View the content to be merged
git diff $(git merge-base main feature) feature

# Or use the three-point syntax
git diff main...feature

4. Resolving Merge Conflicts

(1) The Origins of Conflict

When two branches modify the same location in the same file, Git cannot automatically merge them, resulting in a conflict.

▶ Example: Conflict

BASH
# Modifying Files on a Branch
echo "main content" > file.js
git add file.js
git commit -m "Main modification"

# Switch tofeatureBranch
git switch feature

# Modify the same location in the same file
echo "feature content" > file.js
git add file.js
git commit -m "Feature modification"

# Switch back tomainCombine and Merge
git switch main
git merge feature

# Output:
# Auto-merging file.js
# CONFLICT (content): Merge conflict in file.js
# Automatic merge failed; fix conflicts and then commit the result.

(2) View Conflict Status

▶ Example: Analyzing Conflicts

BASH
# View Status
git status

# Output:
# On branch main
# You have unmerged paths.
#   (fix conflicts and run "git commit")
# 
# Unmerged paths:
#   (use "git add <file>..." to mark resolution)
#   both modified:   file.js

# View Conflicting Files
cat file.js

# Output:
# <<<<<<< HEAD
# main content
# =======
# feature content
# >>>>>>> feature

# View Conflict Details
git diff

# Output:
# <<<<<<< HEAD
# -main content
# =======
# -feature content
# >>>>>>> feature

(3) Resolving Conflicts

▶ Example: Resolving Conflicts Manually

BASH
# Editing Files with Conflicts,Select the content to keep
cat file.js

# Method1:RetainmainChanges to
# main content

# Method2:RetainfeatureChanges to
# feature content

# Method3:Merge the changes from both
# main content
# feature content

# Mark the conflict as resolved
git add file.js

# Complete the merger
git commit

# Output:
# [main d4e5f6g] Merge branch 'feature'

(4) Using Tools to Resolve Conflicts

▶ Example: Using the Merge Tool

BASH
# Using a Graphical Merge Tool
git mergetool

# Using Specific Tools
git mergetool --tool=vimdiff

# View available merge tools
git mergetool --tool-help

# UsagecheckoutSelect a Version
git checkout --ours file.js      # Select the current branch version
git checkout --theirs file.js    # Select a branch version to merge

(5) Detailed Explanation of Conflict Markers

TEXT
<<<<<<< HEAD
Content of the current branch(HEAD)
=======
To merge the contents of the branches
>>>>>>> feature

5. Merger Strategy

(1) Merge Strategy Options

Git supports a variety of merge strategies:

Strategy Description Use Case
recursive (default) Recursive three-way merge Most cases
octopus Merging multiple branches Automatically used when merging multiple branches
ours Ignore other branches Keep the current branch
theirs Ignore the current branch Keep the branch to be merged
resolve Simple three-way merge Special cases

▶ Example: Using a Merge Strategy

BASH
# UsagerecursiveStrategy(Default)
git merge feature

# UsageoursStrategy(IgnorefeatureChanges to)
git merge -s ours feature

# UsagerecursiveStrategy Options
git merge -X ours feature    # In case of a conflict, prioritize the current branch
git merge -X theirs feature  # In the event of a conflict, prioritize the branch to be merged
git merge -X ignore-space-change feature  # Ignore changes in whitespace

(2) Compression and Merging

Compress multiple commits into a single commit and then merge them.

▶ Example: Compress and Merge

BASH
# Compress and Merge
git merge --squash feature

# View Status
git status

# Output:
# Changes to be committed:
#   new file:   feature1.js
#   new file:   feature2.js

# Commit the compressed changes
git commit -m "Merge feature branch (squashed)"

# Advantages:Keep the main branch history clean
# Disadvantages:LostfeatureDetailed History of the Branch

(3) Merge only, do not commit

▶ Example: Preview Merge

BASH
# Merge but do not commit automatically
git merge --no-commit feature

# View the merge results
git status
git diff --staged

# If you're satisfied,Manual Submission
git commit -m "Merge feature branch"

# If you are not satisfied,Cancel Merge
git merge --abort

6. Merging Operations

(1) Suspension of the Merger

▶ Example: Canceling an Ongoing Merge

BASH
# Conflicts Arising from Mergers
git merge feature
# CONFLICT (content): Merge conflict in file.js

# Cancel Merge,Restore to the state prior to the merge
git merge --abort

# Or usereset
git reset --merge

(2) View Merge History

▶ Example: View a merged commit

BASH
# View All Merge Commits
git log --merges --oneline

# Output:
# d4e5f6g Merge branch 'feature'
# a1b2c3d Merge branch 'develop'

# View Unmerged Commits
git log --no-merges --oneline

# View details of the merge
git show --stat d4e5f6g

(3) Revoke the Merger

▶ Example: Undoing a Completed Merge

BASH
# Undo the Last Merge(Merge requests are still available)
git reset --hard HEAD~1

# UsagerevertRevoke Merger(Create a New Commit)
git revert -m 1 HEAD

# -m 1 Indicates that the first parent commit is being preserved(mainBranch)

# View Results
git log --oneline --graph

❓ FAQ

Q What is the difference between a fast-forward merge and a three-way merge?
A A fast-forward merge is performed when the target branch has no new commits; it simply moves the pointer without creating a merge commit. A three-way merge is performed when both branches have new commits; it finds a common ancestor to merge and creates a merge commit.
Q How do I resolve merge conflicts?
A Edit the file with conflicts, remove the conflict markers (<<<<<<<, =======, >>>>>>>), keep the content you need, then use git add to mark the conflict as resolved, and finally use git commit to complete the merge.
Q When should I use the --no-ff option?
A Use this when you want to preserve the branch history and clearly indicate that this is a merge operation. It is typically used when merging a feature branch into the main branch so that the merge point is visible in the history.
Q How do I cancel a merge that is in progress?
A Use git merge --abort to cancel the merge and revert to the pre-merge state. If you have already resolved some of the conflicts, you can also use git reset --merge to reset.
Q What is the difference between a squash merge and a regular merge?
A A squash merge compresses all commits on a branch into a single commit, without preserving the branch's detailed history. The advantage is that the main branch history remains concise; the disadvantage is that the branch's commit history and contextual information are lost.

📖 Summary


📝 Exercises

  1. Basic Exercise: Create two branches, modify different files on each branch, and then merge them to experience the difference between a fast-forward merge and a three-way merge.

  2. Advanced Exercise: Simulate a conflict scenario: Make changes to the same location in the same file on two branches; when merging, a conflict occurs; manually resolve the conflict and complete the merge.

  3. Challenge: Merge branches using different merge strategies (--no-ff, --squash, -X ours, etc.), and compare the results and appropriate use cases for each strategy.

Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏