In this blog, we will learn about the concept of a merge conflict in Git. We will understand what it is and explore its types. We will also learn the different scenarios in which they may arise and a practical understanding of how to identify them in a Git environment. Moreover, we will explore the techniques and strategies for resolving Git merge conflicts effectively.
Table of Contents
Watch this expert-led YouTube video to understand Git conflicts in detail
What is a Merge Conflict in Git?
The merge function of Git allows the integration of changes from multiple branches into a single branch. A merge conflict happens when conflicting commits are made to a file in different branches and Git tries to merge them. This means Git is unable to resolve the differences and cannot decide which changes to incorporate into the final version of that file. Let’s understand this with the help of an example:
Consider that two developers are working on the same project. They both try to make changes to the code in that file. One of the developers pushes the file to the repository after editing the code on lines 15 and 16, and another developer makes the changes to the file on lines 16 and 17. When the second developer tries to push the file back to the repository, a conflict arises on the overlapping line 16 because Git cannot decide which change to keep. This situation may also arise when one developer deletes a file that another developer has modified. In this case, Git will not be able to merge the changes and will report a conflict.
Join Intellipaat’s Git and GitHub Certification Training Course to become an expert in Git and GitHub.
Types of Git Merge Conflicts
A Git merge may become conflicted in two situations: while starting the merge process and during the merge process. We will discuss both scenarios in detail in the section below:
1. While Starting the Merge Process: When you try to merge changes in Git, the process may fail to start if you have unsaved changes in your current project—either in the working directory or the staging area. Git does this to prevent accidental overwriting of your pending local changes by the incoming changes from the branch you’re merging. If you have made modifications to files and haven’t committed them yet, Git considers these changes pending. This precaution ensures that the merge process begins with a clean slate, reducing the risk of conflicts and maintaining the integrity of your local work. It’s not about conflicts with other developers; rather, it’s a measure to avoid conflicts with your ongoing changes. Committing your local changes before starting a merge is a good practice to ensure a smooth and predictable merging process.
2. During the Merge Process: When a failure occurs during a merge in Git, it implies a conflict between the current local branch and the branch that is being merged. This conflict arises when changes have been made to the same lines of code in both branches, leading Git to be unable to automatically merge the differences.
In this situation, Git will make an effort to merge the files automatically, but when it encounters conflicting changes, it leaves the resolution to the user. Git marks these conflicts in the affected files, clearly indicating the sections where conflicting changes exist.
To resolve the conflict, the user needs to manually review the conflicted areas in the files, decide which changes to keep, and then inform Git of the resolution by marking the conflict as resolved. It is to make sure that the user has control over how conflicting changes are integrated. After resolving the conflicts, the user can proceed to complete the merge by committing the changes. This manual interference is necessary to ensure that the merged code functions as intended, with contributions from both branches.
Learn about the version control system and its hosting services in our Git and GitHub training!
How to Identify Merge Conflicts in Git?
We will see an example to see how we can identify merge conflicts using the command line. In this example, we will first create a merge conflict deliberately. Then we will see different commands that will help us identify whether the file is conflicted or not.
$ mkdir my-git-repo #command to create new directory
$ cd my-git-repo #command to navigate to our new directory
$ git init . #command to initialize Git rep
$ echo "initial content for demo" > example.txt #command to create a file example.txt with on line content in it
$ git add example.txt #command to add file in staging area
$ git commit -m "Initial commit with example.txt" #command to commit our changes
[main (root-commit) abcdef1] Initial commit with example.txt
1 file changed, 1 insertion(+)
create mode 100644 example.txt
In this example, we’ve created a new directory named my-git-repo. Afterward, we initialized a Git repository and added an initial file named example.txt with some content. We then committed this initial state to the main branch by using Git.
This code represents the process of setting up a Git repository and making an initial commit with some content. It provides a starting point for further changes and potential merges.
$ git checkout main #command to change branch to main branch
$ git checkout -b feature_branch #command to change branch to feature branch
$ echo "new content in feature branch" >> example.txt
$ git commit -am "Added new content in feature branch"
$ git checkout main
$ echo "conflicting changes in the main branch" >> example.txt
$ git commit -am "Conflicting changes in the main branch"
$ git merge feature_branch #command to merge feature branch
In this example, we create a new branch (feature_branch), make changes to the ‘example.txt’ file, and commit those changes. Then, we switch back to the ‘main’ branch, make conflicting changes to the same file, and commit those changes. Finally, when we attempt to merge the ‘feature_branch’ into the ‘main’ branch, it will result in the following output:
CONFLICT (merge conflict): example.txt
Automatic merge failed; fix conflicts and then commit the result.
This output clearly states that a conflict has occurred.
Git Commands to Resolve Merge Conflicts
To get information about the conflicted files, we will use different commands. We will see those Git commands one by one.
1. We can use the git status command for the same file we created in the above example, i.e., ‘example.txt’. The output of this command will show the unmerged paths due to conflicting changes in the ‘example.txt’ file, as shown below:
$ git status
We will get the following output-
On branch mainYou 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: example.txtno changes added to commit (use "git add" and/or "git commit -a")
2. Another command we can use for this purpose is git log –merge. When you run git log –merge, you’ll see a list of commits that specifically involve merging conflicts. This helps you understand the branching and merging patterns in your file and review the history of how different branches were integrated. The syntax for using this command is shown below:
$ git log --merge
3. We can also use the git diff command. This command helps identify conflicts in the status of a repository or file. We can use it as shown below:
$ git diff
Learn about the important terminologies in our blog on Git Cheat Sheet!
How to Resolve Merge Conflicts in Git?
We have identified the file that is raising the conflict. Now, to resolve the conflict in the above example, we need to manually edit the conflicted file to combine the changes from both branches. The steps for this purpose are mentioned below:
1. Open ‘example.txt’ (filename) in a text editor. You will see conflict markers in the file that indicate the conflicting changes. The conflict markers look like this:
$ git mergetool -t code example.txt
Conflicting changes in main branch
new content in feature branch
The content between <<<<<<< HEAD and ======= represents the changes in the current branch (main) and the content between ======= and >>>>>>> feature_branch represents the changes in the branch being merged (feature_branch).
2. Manually edit the file to choose which changes to keep. You can keep one set of changes, combine them, or make entirely new changes. For example, here we are combining the changes from both branches :
Conflicting changes in the main branch
new content in a feature branch
3. After resolving the conflicts, save the file and stage the resolved file using the following command:
$ git add example.txt
4. Complete the merge with a new commit:
$ git commit -m "Resolved merge conflict in example.txt"
After these steps, the merge conflict should be resolved. Now, if you want to check if the conflict has been resolved, you can use the git status command. It will help you identify if your file is still conflicted.
Are you preparing for jobs? Check out the most important Git interview questions!
Conflicts that can be Resolved in the User Interface
Merge conflict can also be resolved in the GitLab user interface, but only if the following conditions are satisfied:
- The file should be present under the same path in all branches.
- The file should be in text format, not binary format.
- The file should be in a UTF-8 compatible encoding.
- The file should be less than 200 KB in size, with conflict markers added.
If the file can’t meet all of these criteria, you will have to resolve the conflict manually.
Git merge conflicts are not difficult to handle. You can speed up the resolution process by using Git’s built-in tools, being organized, and interacting with your team. Always remember to pull frequently, commit often, and resolve disputes quickly. Remain composed, go over adjustments thoroughly, and work with teammates as needed. Accept the learning curve; software development benefits greatly from knowing how to resolve conflicts. As you and your team work together more frequently, you’ll discover that handling merge disputes comes naturally to you.
Do you still have questions? Post it on Intellipaat’s GitHub Community.