BudiBadu Logo
Samplebadu

Git by Example: Three-Way Merge

2.43.0

Learn how Git handles divergent history using a three-way merge. This process creates a new merge commit to tie together two independent lines of development.

Code

# 1. Create a feature branch and commit
git switch -c feature-diverge
echo "Feature work" > feature.txt
git add feature.txt
git commit -m "Add feature work"

# 2. Switch back to main and make a DIFFERENT commit
git switch main
echo "Mainline work" > main.txt
git add main.txt
git commit -m "Add mainline work"

# 3. Merge the feature branch
git merge feature-diverge

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

# 4. Verify the branching history
git log --oneline --graph --all

# Output:
# *   9g8h7i (HEAD -> main) Merge branch 'feature-diverge'
# |# | * 5e6f7g (feature-diverge) Add feature work
# * | 3c4d5e Add mainline work
# |/
# * 1a2b3c Initial commit

Explanation

A three-way merge is required when the history of the two branches has diverged. This means that since the feature branch was created, new commits have also been added to the main branch. In this case, a simple fast-forward is impossible because there is no single linear path that includes all changes.

Git solves this by performing a three-way comparison. It looks at three specific snapshots: the tip of the current branch (HEAD), the tip of the branch being merged, and the common ancestor of both branches. By comparing these three points, Git can intelligently combine the changes. If the changes are in different files or different parts of the same file, Git merges them automatically.

The result of a three-way merge is a special merge commit. Unlike normal commits which have one parent, a merge commit has two parents: the last commit from the main branch and the last commit from the feature branch. This commit ties the two histories together, creating a visual "diamond" shape in the commit graph.

  • Required when branches have diverged
  • Uses a common ancestor to calculate changes
  • Creates a new merge commit with two parents
  • Preserves the history of parallel development

Code Breakdown

15
Executes the merge. Since 'main' has progressed independently (commit 3c4d5e), Git must perform a full merge strategy (defaulting to 'ort' or 'recursive').
26
The log graph shows the divergence. The commit 9g8h7i is the new merge commit that joins the two separate lines of history.
28-29
These lines represent the parallel development. One branch added "feature work" while the other added "mainline work" at the same time.