Git & GitHub

Merging Branches

13 min Lesson 10 of 35

Merging Branches

Merging is how you integrate changes from one branch into another. In this lesson, you'll learn different merge types, how to resolve conflicts, and best practices for keeping your project history clean and organized.

What is Merging?

Merging combines the changes from one branch (source) into another branch (target):

Common Merge Scenarios: - Merge feature branch into main (after development) - Merge main into feature branch (keep feature updated) - Merge bugfix into release branch - Merge hotfix into both main and develop
Key Concept: A merge creates a new commit that has two parents - one from each branch being merged. This preserves the complete history of both branches.

Basic Merge Command

The fundamental merge workflow:

# Switch to target branch (where you want changes) git switch main # Merge source branch into current branch git merge feature-branch # View merge result git log --oneline --graph # If successful, the feature branch changes are now in main

Fast-Forward Merge

When the target branch hasn't changed since the source branch was created:

# Scenario: main hasn't changed since feature branch created main: A---B \ feature: C---D # After merge (fast-forward): main: A---B---C---D feature: C---D # Fast-forward merge command: git switch main git merge feature-branch # Output: "Fast-forward" # No merge commit created - just moves pointer forward
Tip: Fast-forward merges are clean and simple because no actual merging needs to happen - Git just moves the branch pointer forward. The history remains linear.

Three-Way Merge

When both branches have new commits since they diverged:

# Scenario: Both branches have changes main: A---B---E---F \ feature: C---D # After three-way merge: main: A---B---E---F---M \ / feature: C---D---/ # M is the merge commit with two parents # Three-way merge command: git switch main git merge feature-branch # Git creates a merge commit automatically
Understanding: Three-way merge uses three commits: the common ancestor, the tip of the target branch, and the tip of the source branch. Git intelligently combines changes from both branches.

No Fast-Forward Merge

Force creation of a merge commit even when fast-forward is possible:

# Always create merge commit (preserves branch history) git merge --no-ff feature-branch # Why use --no-ff? ✓ Explicitly shows that a feature was merged ✓ Makes it easy to revert entire features ✓ Preserves context about branch existence ✓ Better for team workflows # Example merge commit message: Merge branch 'feature-login' This feature adds user authentication with: - Login form - Password validation - Session management

Merge Conflicts

Conflicts occur when Git can't automatically merge changes:

Conflicts happen when: - Same line edited in both branches - File deleted in one branch, modified in another - Same file added with different content - Binary files changed in both branches # When conflict occurs: git merge feature-branch # Auto-merging file.txt # CONFLICT (content): Merge conflict in file.txt # Automatic merge failed; fix conflicts and then commit
Important: When a merge conflict occurs, Git stops in the middle of the merge. You must resolve all conflicts and complete the merge manually before continuing work.

Understanding Conflict Markers

Git marks conflicts in files with special markers:

# Conflicted file content: <<<<<<< HEAD const greeting = "Hello from main branch"; ======= const greeting = "Hello from feature branch"; >>>>>>> feature-branch Marker Meanings: <<<<<<< HEAD - Start of your current branch changes ======= - Separator between the two versions >>>>>>> feature-branch - End marker showing source branch # Your job: Choose which version to keep (or combine them)

Resolving Merge Conflicts

Step-by-step conflict resolution:

# Step 1: Identify conflicted files git status # Both modified: file.txt # Both modified: app.js # Step 2: Open conflicted files and edit # Remove conflict markers and choose correct code: # Before (conflicted): <<<<<<< HEAD const version = "1.0"; ======= const version = "2.0"; >>>>>>> feature-branch # After resolution (choose one or combine): const version = "2.0"; # Step 3: Mark as resolved git add file.txt git add app.js # Step 4: Complete the merge git commit # Git opens editor with merge commit message # You can edit or accept default message # Step 5: Verify merge git log --oneline --graph
Pro Tip: Use git diff to see conflicts before resolving: git diff --name-only --diff-filter=U shows only unmerged files.

Merge Conflict Resolution Strategies

Strategy 1: Accept Current Branch (Ours) git checkout --ours file.txt git add file.txt Strategy 2: Accept Incoming Branch (Theirs) git checkout --theirs file.txt git add file.txt Strategy 3: Manual Edit # Open file in editor, manually resolve vim file.txt git add file.txt Strategy 4: Use Merge Tool git mergetool # Opens configured visual merge tool # Popular tools: meld, kdiff3, vimdiff, VS Code

Aborting a Merge

If conflicts are too complex or you need to reconsider:

# Abort merge and return to pre-merge state git merge --abort # This is safe - restores everything to before merge # Use when: ✓ Conflicts are too complex to resolve immediately ✓ You merged the wrong branch ✓ You need to consult with team members ✓ You want to try a different approach (rebase)

Merge Strategies

Git supports different merge strategies for special situations:

# Default recursive strategy (used automatically) git merge feature-branch # Ours strategy - keep only current branch changes git merge -s ours old-branch # Theirs strategy (via option) - prefer incoming changes git merge -X theirs feature-branch # Octopus strategy - merge multiple branches at once git merge branch1 branch2 branch3 # Resolve strategy - for two branches (rarely used) git merge -s resolve feature-branch
Common Use: -X theirs and -X ours are useful when you always want to prefer one side in conflicts. Example: git merge -X theirs main updates your feature branch, preferring main's changes in conflicts.

Best Practices for Merging

Before Merging: ✓ Ensure working directory is clean ✓ Make sure you're on correct target branch ✓ Pull latest changes from remote ✓ Review what will be merged (git log, git diff) ✓ Run tests to ensure code works During Merge: ✓ Read conflict markers carefully ✓ Test after resolving each conflict ✓ Don't blindly accept one side ✓ Communicate with authors of conflicting code ✓ Write clear merge commit messages After Merge: ✓ Run full test suite ✓ Verify application still works ✓ Push merged changes promptly ✓ Delete merged feature branches ✓ Inform team of merge completion

Practical Merge Workflow

Complete real-world merge example:

# Scenario: Merge feature-login into main # 1. Prepare main branch git switch main git pull origin main # 2. Preview merge git log main..feature-login --oneline git diff main..feature-login --stat # 3. Perform merge git merge --no-ff feature-login # 4a. If no conflicts: # Edit merge message if needed, save and exit git push origin main # 4b. If conflicts occur: git status # See conflicted files # Edit conflicted files, resolve conflicts git add resolved-file1.txt git add resolved-file2.js git commit # Complete merge # 5. Verify and test git log --oneline --graph -5 npm test # Run tests # 6. Clean up git branch -d feature-login git push origin --delete feature-login

Using Merge Tools

Visual tools make conflict resolution easier:

# Configure merge tool (one-time setup) git config --global merge.tool vscode git config --global mergetool.vscode.cmd 'code --wait --merge $REMOTE $LOCAL $BASE $MERGED' # Or use built-in tools git config --global merge.tool vimdiff # When conflicts occur, launch merge tool git mergetool # Merge tool shows three panels: # - LOCAL: Your current branch changes # - BASE: Common ancestor version # - REMOTE: Incoming branch changes # - MERGED: Result you're creating # After resolving in tool, save and exit git commit

Practice Exercise:

Scenario: Practice complete merge workflow with conflict resolution:

  1. Create two branches from main: feature-a and feature-b
  2. In both branches, modify the same line in the same file
  3. Merge feature-a into main (should succeed)
  4. Try merging feature-b into main (will conflict)
  5. Resolve the conflict and complete the merge

Commands:

# 1. Create branches git switch main git switch -c feature-a echo "Version A" > file.txt git add file.txt git commit -m "Feature A changes" git switch main git switch -c feature-b echo "Version B" > file.txt git add file.txt git commit -m "Feature B changes" # 2. Merge feature-a (no conflict) git switch main git merge feature-a # 3. Try merging feature-b (conflict!) git merge feature-b # CONFLICT! # 4. Resolve conflict git status # See conflicted file # Edit file.txt, choose "Version B" or combine echo "Version B (resolved)" > file.txt git add file.txt # 5. Complete merge git commit git log --oneline --graph # Clean up git branch -d feature-a feature-b

Merge vs Rebase

Quick comparison (we'll explore rebase in detail later):

Use Merge When: ✓ Working on shared/public branches ✓ Want to preserve complete history ✓ Merging long-lived branches ✓ Team prefers explicit merge commits ✓ Working with multiple contributors Use Rebase When: ✓ Working on private/local branches ✓ Want linear, clean history ✓ Updating feature branch with main ✓ Preparing branch for merge/PR ✓ Solo work or small team with coordination Golden Rule: Never rebase public branches that others work on!

Summary

In this lesson, you learned:

  • What merging is and why it's essential for collaboration
  • Fast-forward vs three-way merge differences
  • Creating explicit merge commits with --no-ff
  • Understanding and identifying merge conflicts
  • Reading conflict markers and resolving conflicts manually
  • Using merge strategies (--ours, --theirs)
  • Aborting merges safely with git merge --abort
  • Using visual merge tools for easier resolution
  • Complete merge workflow best practices
  • When to use merge vs rebase
Next Up: In the next lesson, we'll explore rebasing - an alternative to merging that creates a linear history by replaying commits!

ES
Edrees Salih
17 hours ago

We are still cooking the magic in the way!