Fun with Learning Technology
LearnCoursesQuestionsTracksToolsNewsExplorePractice
Fun with Learning Technology

A new problem, explained clearly, every day.

Subscribe
Learn
  • Lessons
  • Topics
  • News
  • Tools
  • Courses
  • Career tracks
  • Everything
Site
  • About
  • Contact
  • Support
  • Privacy
  • Terms
Get the daily one

One email per new problem. No spam.

Request a tutorial

Requests shape what gets made next.

© 2026 Fun with Learning TechnologyRSS
Home›Courses›Git & GitHub›Conflict Resolution

Branching and Merging

Conflict Resolution

Conflict resolution is the systematic process of manually reconciling divergent changes made to the same lines of code within a repository. It is essential for maintaining project integrity when automated merge tools fail to determine the intended state of a file during integration. You reach for this process whenever Git pauses a merge operation, signaling that it cannot safely combine history without human intervention.

Understanding the Merge State

A merge conflict occurs when the Git engine detects that two branches have modified the same segment of a file in incompatible ways. Git operates by tracking snapshots of project states, and when it attempts to weave two histories together, it looks for common ancestors. If both branches have altered the same lines since that ancestor, Git cannot mathematically decide which version represents the 'correct' intended outcome. Consequently, it shifts the repository into a 'merging' state. This state is a temporary hold, preventing further commits until the ambiguity is resolved. The system essentially marks the offending files with conflict markers, effectively offloading the decision-making logic to the developer. By halting the process, Git ensures that no faulty automated assumptions are baked into your codebase, maintaining the integrity of the project history and preventing broken functionality from being silently integrated into the primary development branch.

# Simulate a conflict by modifying the same line in two branches
echo "Initial Content" > project.txt
git add project.txt && git commit -m "Initial commit"
git checkout -b feature-a
echo "Feature A change" >> project.txt
git commit -am "Change in A"
git checkout main
echo "Feature B change" >> project.txt
git commit -am "Change in B"
git merge feature-a # This will trigger a conflict error

Anatomy of Conflict Markers

When a conflict occurs, Git embeds special visual markers into the affected files to indicate the nature of the disagreement. The '<<<<<<< HEAD' marker denotes the starting point of the changes present in your current branch, which is the version you are merging into. The '=======' separator acts as the boundary, physically splitting your local changes from the incoming changes. Below this, the '>>>>>>>' marker identifies the incoming branch being merged. These markers are not merely suggestions; they are raw text injected into your file by Git to show you the conflicting snapshots side-by-side. To resolve the conflict, you must delete these markers and manually edit the text until the file reflects the desired logic. This structure forces you to look at the exact divergence in history, ensuring that you don't accidentally overwrite critical logic from another developer while finalizing your own changes to the project's logic and structure.

# After running git merge, opening project.txt shows:
# <<<<<<< HEAD
# Feature B change
# =======
# Feature A change
# >>>>>>> feature-a

# To resolve, manually edit to look like this:
# Feature A and B integrated

# Save the file and prepare to conclude the process

Finalizing the Resolution

After you have manually edited the file to address the conflict, you have essentially moved the repository back into a consistent state. However, Git does not know you are finished until you explicitly tell it so. The 'git add' command is the mechanism used to inform Git that the file has been repaired and the conflict markers have been purged. Once the file is added to the staging area, it is marked as 'resolved' in the Git index. You can then proceed to finalize the merge by performing a commit. This final commit is unique because it possesses two parent commit objects, representing the joining of the two divergent branches. This is the moment where the history actually reconciles, turning the separate paths into a unified single timeline. Without this step, your repository would remain trapped in a pending merge state, making further operations impossible to perform safely.

# Stage the file to indicate the conflict is resolved
git add project.txt

# Finalize the merge, which creates a new merge commit
git commit -m "Merged feature-a into main with manual fixes"

# Verify status is clean
git status

Using Git Mergetool for Visual Aid

Manually editing text files containing conflict markers can be prone to human error, especially in complex codebases where multiple blocks might conflict simultaneously. Git provides a 'mergetool' command to streamline this process, allowing you to use a dedicated visual interface to view the changes. When you trigger 'git mergetool', Git opens a configured external application that displays three or four windows: the local version, the remote version, the common base ancestor, and the final result window. This setup allows you to reason about the evolution of the code by seeing exactly what each contributor changed relative to the original source. By selecting specific lines or blocks from these views, you can synthesize the correct file content with greater confidence. This tool reduces the cognitive load of manual resolution and helps prevent accidental deletion of critical logic during the merge process, ensuring that the integration is clean and well-verified before committing.

# List available mergetools
git mergetool --tool-help

# Launch the configured tool (e.g., vimdiff, kdiff3, or others)
git mergetool

# After saving the resolution in the tool, finish the commit
git commit -m "Resolved conflicts via mergetool"

Aborting a Failed Merge

There are instances where a conflict is far more complex than initially anticipated, or perhaps the merge has revealed a fundamental incompatibility in the design architecture that requires deeper investigation. In these scenarios, you should not feel forced to finish the merge immediately. Git offers an 'abort' command that allows you to safely back out of the merge process entirely. Running this command resets your repository back to the exact state it was in before you initiated the merge command, effectively cleaning up the conflict markers and the temporary merge state. This is an essential safety feature for professional workflows, as it prevents you from making hasty, ill-conceived fixes just to get the code to compile. By aborting, you can research the root cause, communicate with the other contributor, or update your local branch before attempting the merge again later under better-informed circumstances.

# If you realize the merge is too complex, abandon it
git merge --abort

# The repository is now back to its pre-merge state
git status # Should show 'nothing to commit'

# You can now regroup and try the merge again later

Key points

  • A merge conflict indicates that Git cannot automatically reconcile divergent changes to the same file lines.
  • The repository enters a pending merge state that blocks further actions until the conflict is resolved.
  • Conflict markers are text injected by Git to delineate the local version from the incoming branch changes.
  • Resolving a conflict requires manually editing the file to remove markers and finalize the desired code structure.
  • Using git add after manual editing notifies Git that the specific file's conflict has been successfully addressed.
  • A merge commit is the final step that links two divergent branches into a single, unified project history.
  • Visual mergetools provide a side-by-side comparison of local and remote changes to reduce manual resolution errors.
  • The git merge --abort command safely reverts the repository to the state existing before the merge attempt began.

Common mistakes

  • Mistake: Manually resolving conflicts by deleting markers without verifying the code logic. Why it's wrong: You might inadvertently delete functional code or create syntax errors. Fix: Always review the merged code after removing markers and run your local build tests.
  • Mistake: Ignoring 'both modified' messages and choosing 'theirs' or 'ours' blindly. Why it's wrong: This discards valuable changes from the other contributor, leading to regressions. Fix: Use a diff tool to understand what each side changed before accepting one version.
  • Mistake: Committing conflict markers (<<<<<<<) directly to the repository. Why it's wrong: These symbols break the build and make the history messy. Fix: Ensure you have fully resolved the conflict and staged the file before attempting to commit.
  • Mistake: Attempting to resolve a merge conflict during a rebase without using 'git rebase --continue'. Why it's wrong: The rebase state stays stuck, and Git cannot proceed with the next commit. Fix: After resolving the conflict, stage the files and then run 'git rebase --continue'.
  • Mistake: Resolving conflicts in a shared feature branch by pushing a hard reset. Why it's wrong: This disrupts the work of other collaborators who have pulled the branch. Fix: Pull the latest changes, resolve conflicts locally, and then push your changes normally.

Interview questions

What exactly is a merge conflict in Git and when does it typically occur?

A merge conflict occurs in Git when the version control system cannot automatically reconcile differences in code between two commits being merged together. This typically happens when two developers modify the same line in a file in different ways, or when one developer deletes a file while another modifies it. Git pauses the process, marks the specific files with conflict markers like <<<<<<<, =======, and >>>>>>>, and requires a human to manually decide which changes to keep or how to integrate both, ensuring the codebase remains consistent before the commit can be completed.

What is the standard step-by-step workflow for resolving a merge conflict locally?

To resolve a conflict, first run 'git status' to identify the conflicting files. Open these files in your editor to locate the conflict markers. You must manually edit the file to choose the desired code, removing the markers entirely. Once the file is correct, stage the resolved file using 'git add <filename>'. Finally, complete the resolution by running 'git commit' to create a new merge commit. This manual intervention is crucial because Git cannot interpret business logic or intended functionality, and it ensures that you verify the code integrity before finalizing the branch integration.

How can you use GitHub's web interface to resolve conflicts without using the command line?

GitHub provides a 'Resolve conflicts' button directly within the Pull Request view when a branch cannot be automatically merged. When clicked, it opens a browser-based editor that highlights the conflicting blocks. You can edit the code directly in the browser to remove the conflict markers and fix the code, then click 'Mark as resolved'. Once all files are addressed, you click 'Commit merge', which automatically creates a merge commit on the branch. This is highly effective for minor textual conflicts and allows team members who might not be proficient with command-line tools to contribute to conflict resolution safely within the cloud environment.

Compare the strategy of using 'git merge' versus 'git rebase' when handling conflicting histories.

Merging creates a new 'merge commit' that ties two histories together, preserving the exact chronological order of commits, which is excellent for audit trails but can result in a messy, non-linear branch history. Rebasing, conversely, moves your entire feature branch to start from the tip of the target branch, rewriting commit history to create a clean, linear path. While rebasing makes the project history look much cleaner, it can be dangerous if performed on shared public branches, as it changes existing commit hashes and can confuse teammates. Choose merging for safety and full history preservation, or rebasing for a cleaner project timeline.

What are Git rerere and its role in handling repetitive conflict resolution?

Git rerere, short for 'reuse recorded resolution', is a powerful feature that instructs Git to remember how you resolved a specific conflict in a file. If the same conflict appears again—for example, during a lengthy rebase process where you have to resolve conflicts repeatedly—Git will automatically apply the previous resolution. This saves immense time and reduces human error during complex branch integrations. You enable it via 'git config --global rerere.enabled true'. It is a pro-level tool that acts as an automated memory for your conflict-solving patterns, making maintenance of long-running branches significantly more efficient and less prone to manual typos.

How do you handle a situation where a merge conflict resolution causes a regression in functionality?

If a conflict resolution introduces a bug, you must first identify the faulty merge commit using 'git log'. If the issue is severe, use 'git reset --hard HEAD~1' to revert the merge entirely, or if the change is already pushed, use 'git revert -m 1 <commit_hash>' to create a new commit that undoes the changes. The best prevention strategy is to run your automated test suite immediately after resolving the conflict but before committing. By validating the build with tests, you ensure that the manual reconciliation of code logic didn't inadvertently break existing features, maintaining the stability of your repository's main branch.

All Git & GitHub interview questions →

Check yourself

1. What is the primary purpose of the conflict markers (<<<<<<<, =======, >>>>>>>) that Git inserts into files?

  • A.To signify that the file is corrupt and must be deleted
  • B.To identify the specific sections of code that were modified by different branches
  • C.To inform the system which branch is currently the active HEAD
  • D.To provide a backup of the original file before the merge attempt
Show answer

B. To identify the specific sections of code that were modified by different branches
These markers clearly demarcate the content from the HEAD (yours) and the branch being merged (theirs). Option 0 is wrong because the file is not corrupt. Option 2 is wrong because markers don't track the HEAD status. Option 3 is wrong because they do not act as backups.

2. After you have successfully edited the conflicted files to remove all markers, what is the next step you must perform?

  • A.Run 'git merge --continue'
  • B.Run 'git push' to update the remote server
  • C.Stage the resolved files using 'git add'
  • D.Create a new branch for the resolved code
Show answer

C. Stage the resolved files using 'git add'
Git requires you to explicitly stage the resolved files to tell it that the conflict is handled. Option 0 is not a standard Git command. Option 1 is premature as you haven't finished the merge commit. Option 3 is unnecessary and creates redundant workflow complexity.

3. What happens if you resolve a conflict and commit it, but leave one of the marker symbols (e.g., '=======') inside the file?

  • A.Git automatically detects the symbol and removes it during the next push
  • B.The code will likely result in a syntax error when compiled or executed
  • C.Git will refuse to merge the branch entirely
  • D.The file will be treated as a binary file by Git
Show answer

B. The code will likely result in a syntax error when compiled or executed
Git does not validate code syntax; it sees the marker as part of the text, which will cause issues in your source code. Option 0 is false as Git doesn't 'auto-clean' code. Option 2 is false as the merge is already committed. Option 3 is false as Git is agnostic to file types.

4. Why is 'git merge' often preferred over 'git rebase' when dealing with complex conflicts in a shared team branch?

  • A.Merge creates a record of the conflict resolution through a merge commit
  • B.Rebase is incapable of handling conflicts
  • C.Merge automatically fixes all logic errors during the resolution process
  • D.Rebase requires significantly more RAM on the local machine
Show answer

A. Merge creates a record of the conflict resolution through a merge commit
Merge commits provide a clear point in history showing when and how branches joined. Option 1 is false because rebase handles conflicts fine. Option 2 is false because code logic is the developer's responsibility. Option 3 is irrelevant to Git's performance.

5. When you are in the middle of a conflict resolution process and realize you made a mistake, how do you safely revert back to the state before the merge?

  • A.Delete the local repository and clone it again
  • B.Run 'git reset --hard HEAD'
  • C.Run 'git merge --abort'
  • D.Modify the .git/config file to disable conflicts
Show answer

C. Run 'git merge --abort'
The 'git merge --abort' command is the safe, intended way to stop the process and return to the pre-merge state. Option 0 is overkill and unnecessary. Option 1 would wipe all your recent local work. Option 3 is impossible as configuration cannot disable conflict detection.

Take the full Git & GitHub quiz →

← PreviousCherry-picking CommitsNext →Remotes — push, pull, fetch

Git & GitHub

20 lessons, free to read.

All lessons →

Track your progress

Sign in to mark lessons done, score quizzes and keep notes.

Open in the app