This lesson on Resolving Merge Conflicts is hands-on and example-driven. You will learn to diagnose and resolve Git merge conflicts, whether caused by uncommitted local changes or structural file differences. You will gain proficiency in using both command-line tools like git status and git add, and visual IDE features (VS Code) to finalize the merge process.
What You'll Be Able To Do
- Diagnose the cause of a failed merge using git status and git log --merge.
- Safely exit a conflicted state using the git merge --abort command.
- Interpret and manually edit files containing Git conflict markers.
- Stage and commit a resolved merge conflict using the command line interface.
- Utilize VS Code's built-in tools to visually accept or reject conflicting changes.
- Manage uncommitted local changes before a merge using git stash.
Detailed Concept Walkthrough
1. Git's Three-Way Merge Architecture
Git compares the two branch tips (HEAD and incoming) against their common ancestor commit to determine changes, allowing it to auto-merge non-conflicting modifications. Conflicts only arise when the same lines are modified differently in both branches since the common ancestor.
- Mechanism: Git identifies the common ancestor commit shared by both branches being merged. It then calculates the difference (diff) between the ancestor and Branch A (HEAD) and the ancestor and Branch B (Incoming).
- Under the Hood: If changes occur in separate parts of the file, Git automatically combines them; this is the auto-merge algorithm succeeding. A conflict occurs only when the algorithm cannot reconcile simultaneous, overlapping changes to the same section.
- Best Practice: Understanding the three comparison points (Ancestor, HEAD, Incoming) is crucial for interpreting why Git sometimes succeeds and sometimes fails, preventing the misconception that any file modification guarantees a conflict.
Key Takeaway: Conflicts are structural failures in Git's auto-merge algorithm, not just simultaneous file edits.
2. Managing Local Uncommitted Changes
Git prevents merges when the working directory is 'dirty' (contains uncommitted changes) to avoid accidentally overwriting or losing local work during the merge process. This is a critical safety mechanism.
- Mechanism: If you attempt
git mergewhile files are modified but unstaged or staged but uncommitted, Git throws an error stating local changes would be overwritten, halting the operation before any data loss occurs. - Execution Flow: The correct workflow is to temporarily save these changes using
git stash, which cleans the working directory by moving the changes onto a temporary stack, allowing the merge to proceed safely. - Best Practice: Always run
git statusbefore a merge operation; if changes exist, usegit stash pushto save them, andgit stash popto reapply them after the merge is successfully completed.
git status
# Save local changes temporarily
git stash push -m "Saving local changes before merge"
git merge feature/branch
# Reapply saved changes
git stash pop
Key Takeaway: Use
git stashto clear the working directory before merging to prevent the 'local changes will be overwritten' error.
3. Diagnosing and Exiting Conflicts
Once Git fails the structural auto-merge, the repository enters a specific conflicted state, requiring diagnostic tools to identify the files needing manual intervention.
- Mechanism: When a merge fails, Git stops the process and marks the files it couldn't resolve as 'Unmerged Paths.' The repository remains in this transitional state until the conflict is resolved or aborted.
- Tooling:
git statusis the primary diagnostic tool, listing files under 'Unmerged Paths.'git log --mergehelps identify the specific commits from the incoming branch that caused the conflict. - Best Practice: If the conflict is too complex or you need to restart, use
git merge --abort. This command safely returns the repository to the state it was in immediately before the merge attempt, discarding all conflict markers.
git status
# Identify commits involved in the conflict
git log --merge
# Safely exit the conflicted state
git merge --abort
Key Takeaway:
git statusidentifies the files requiring resolution;git merge --abortis the safe exit strategy.
4. Manual Resolution via Markers
Git inserts special markers into conflicted files, isolating the changes from the current branch (HEAD) and the incoming branch, requiring the developer to manually edit the file to create the desired final state.
- Mechanism: Git uses three markers:
<<<<<<< HEAD(start of current branch changes),=======(separator), and>>>>>>> branch-name(end of incoming branch changes). The developer must delete all three markers and the unwanted code block. - Under the Hood:
HEADalways refers to the changes on the branch you currently have checked out (the receiving branch). The text between=======and>>>>>>>is the change from the branch being merged in. - Execution Flow: After manually editing the file to the correct state, the file must be staged (
git add <file>) to signal Git that the conflict is resolved, followed by a finalgit committo complete the merge. - Best Practice: Ensure you delete all conflict markers and only the desired final code remains before staging the file. Utilize IDE tools (VS Code) for visual assistance if manual editing becomes tedious.
// Conflicted file content
<<<<<<< HEAD
function calculate(a, b) { return a + b; }
=======
function calculate(a, b) { return a * b; }
>>>>>>> feature/math-update
Key Takeaway: Manual resolution requires deleting all markers and unwanted code, then staging the file to finalize the merge commit.
Topics Covered in Resolving Merge Conflicts
- Git Merge Mechanism (0:18 - 1:08) — Explains the three-way merge concept and why conflicts occur when the auto-merge algorithm fails.
- Handling Dirty Directory (1:23 - 1:54) — Demonstrates using
git stashto temporarily save uncommitted local changes before attempting a merge. - Diagnosing Conflicts (1:54 - 3:12) — Shows how to use
git statusto identify unmerged paths andgit merge --abortto exit the conflicted state. - Manual Resolution (3:12 - 4:38) — Details the process of interpreting and manually editing files containing the Git conflict markers.
- IDE Tool Resolution (4:43 - 5:15) — Illustrates using visual tools in VS Code to accept or reject changes instead of manual marker deletion.
- Finalizing the Merge (4:38) — Covers staging the resolved file using
git addand completing the process with a final merge commit.
Git Cheat Sheet
-
git stash push— Save uncommitted local changes temporarilygit stash push -m "WIP" -
git status— Show files in conflicted stategit status -
git log --merge— Identify commits causing the conflictgit log --merge -
git merge --abort— Exit a failed merge safelygit merge --abort -
<<<<<<< HEAD— Marker for current branch's changes<<<<<<< HEAD -
git add <file>— Stage a manually resolved filegit add index.js -
git commit— Finalize the merge commitgit commit -m "Resolved conflict"
Comparison Table
| Aspect | Manual CLI Resolution | IDE (VS Code) Resolution |
|---|---|---|
| Tooling | Text editor (Vim, Nano) | Visual interface, buttons |
| Marker Handling | Must manually delete markers | Buttons accept/reject changes |
| Workflow | Edit file, git add, git commit | Click buttons, git add implied |
| Complexity | Better for complex logic | Faster for simple conflicts |
Common Pitfalls
- Mistake: Starting a merge with uncommitted changes.
Avoid: Use
git stashfirst to clean the working directory. - Mistake: Forgetting to delete the conflict markers.
Avoid: Ensure the file is clean before running
git add. - Mistake: Committing the file without staging it first after resolution.
Avoid: Always run
git add <file>before the finalgit commit. - Mistake: Confusing
HEADwith the incoming branch in the markers. Avoid:HEADis always the branch you are currently checked out on.
FAQs
- What does Git compare during a merge? Git compares the tips of both branches against their common ancestor commit (the three-way merge).
- What is the difference between a dirty working directory error and a structural conflict? A dirty working directory error prevents the merge from starting; a structural conflict occurs when the merge fails mid-process due to overlapping changes.
- If I resolve a conflict, do I need a special command to finish?
No, after resolving the file and running
git add, a standardgit commitcompletes the merge process. - Can I use VS Code to resolve conflicts even if I started the merge in the CLI? Yes, IDE tools simply edit the file content; you return to the CLI for staging and committing the result.