Merge Conflicts and How to handle them

Merge conflicts are a common issue in collaborative software development when using version control systems like Git. They occur when changes from different branches clash and Git cannot automatically merge them.

Understanding how to handle merge conflicts is important for maintaining a smooth workflow. This article will explain what merge conflicts are, why they happen, and how to resolve them effectively.

Table of Content

  • What are Merge Conflicts?
  • Common Causes of Merge Conflicts
  • Types of Merge Conflicts
  • Creating a merge conflict
  • Handling the Merge Conflict

What are Merge Conflicts?

A merge conflict arises when Git encounters conflicting changes in the same part of a file from different branches. This typically happens during a merge or rebase operation. Git cannot determine which changes to keep, so it flags the conflict for the developer to resolve manually.

Common Causes of Merge Conflicts

  1. Simultaneous Edits: When multiple developers edit the same lines in a file, Git will not be able to merge the changes automatically.
  2. Overlapping Changes: When changes in different branches overlap, such as one branch renaming a file while another branch edits its content.
  3. Divergent Branches: Long-lived branches that have diverged significantly can result in conflicts when merged back together.

Types of Merge Conflicts

While starting the merge: If there are changes in either the working directory or staging area, while merging, then Git will fail to start the merge. This happens because the pending changes could be overridden by the commits that are being merged. This is the error message provided by Git when this type of merge conflict happens :

error: Entry '<fileName>' not uptodate. Cannot merge. (Changes in working directory)
or,
error: Entry '<fileName>' would be overwritten by merge. Cannot merge. (Changes in staging area)

This type of conflict can be resolved either by doing git stash save “any_message_to_describe_what_is_saved” (Stashes away any changes in your staging area and working directory in a separate index) OR git checkout <file_name> (throws out your changes), and then the merge can be completed.

During the merge: This occurs because you have committed changes that are in conflict with someone else’s committed changes. Git will do its best to merge the files and will leave things for you to resolve manually in the files it lists. This is the error message provided by Git when this type of merge conflict happens :

CONFLICT (content): Merge conflict in <fileName>
Automatic merge failed; fix conflicts and then commit the result.

This type of conflict can be resolved either by manually fixing all the merge conflict for each file OR using git reset ––hard (resets repository in order to back out of merge conflict situation).

Creating a merge conflict

To show a simple example of how a merge conflict can happen, we can manually trigger a merge conflict from the following set of commands in any UNIX terminal / GIT bash :

Step 1: Create a new directory using the mkdir command, and cd into it.

Step 2: initialize it as a new Git repository using the git init command and create a new text file using the touch command.

Step 3: Open the text file and add some content in it, then add the text file to the repo and commit it.

Step 4: Now, its time to create a new branch to use it as the conflicting merge. Use git checkout to create and checkout the new branch.

Step 5: Now, overwrite some conflicting changes to the text file from this new branch.

Step 6: Add the changes to git and commit it from the new branch.

With this new branch: new_branch_for_merge_conflict we have created a commit that overrides the content of test_file.txt

Step 7: Again checkout the master branch, and this time append some text to the test_file.txt from the master branch.

Step 8: add these new changes to the staging area and commit them.

Step 9: Now for the last part, try merging the new branch to the master branch and you will encounter the second type of merge conflict.

So, now we have successfully triggered a merge conflict in Git.

Handling the Merge Conflict

As we have experienced from the proceeding example, Git will produce some descriptive output letting us know that a CONFLICT has occurred. We can gain further insight by running the git status command. This is what we will get after running the git status command:

On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)

Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: test_file.txt

no changes added to commit (use "git add" and/or "git commit -a")

On opening the test_file.txt we see some “conflict dividers”. This is the content of our test_file.txt :

<<<<<<< HEAD
Adding some content to mess with it later
Append this text to initial commit
=======
Changing the contents of text file from new branch
>>>>>>> new_branch_for_merge_conflict

The ======= line is the “center” of the conflict. All the content between the center and the <<<<<<< HEAD line is content that exists in the current branch master which the HEAD ref is pointing to. Alternatively, all content between the center and >>>>>>> new_branch_for_merge_conflict is content that is present in our merging branch.

To resolve our merge conflict, we can manually remove the unnecessary part from any one of the branches, and only consider the content of the branch that is important for further use, along with removing the “conflict dividers” from our file. Once the conflict has been resolved we can use the git add command to move the new changes to the staging area, and then git commit to commit the changes.