Wern Central

Fixing merge conflicts in Git

Published on Dec 28, 2019
Last updated on Sep 30, 2021

Merge conflicts can be confusing, especially to those who are new with Git. You are likely to experience a merge conflict when more than one person is working on the same repository. In this post, we’re going to explore on some basic merge conflict resolution.

Skip to: Resolving merge conflicts

What is a merge conflict?

As the name implies, a merge conflict occurs when Git is unable to automatically merge the changes between two conflicting commits, usually from different branches. This can occur when, for example, more than one person tries to change the same line of code at the same time, and tries to merge the changes. This error message would probably be familiar:

Automatic merge failed; fix conflicts and then commit the result.

If all modifications are on different lines or on different files, Git would automatically help you merge your changes, and you would not experience much of a problem.

Merge conflicts can occur directly as a result of git merge, git rebase, or cherry picking a commit to merge. It can also indirectly occur as a result of not updating your local branch with git pull to be in sync with the remote, thus causing the local branch and remote branch to diverge and requiring a merge.

Resolving Merge Conflicts

There are a few ways you can resolve and fix any merge conflicts you encounter. We’re going to use an example scenario with the code below.

Scenario

if (status == 200) {
	alert('success');
}

Bob and John are simultaneously working on this codebase, and they both currently see this code. They create the branches branch-bob and branch-john respectively to work on updating it.

Here’s what happens at the same time:

  1. Bob has implemented some validation and modifies the code in branch bob:

    if (status == 200 && completed) {
    	alert('success');
    }
  2. John made the following changes in a branch john:

    if (status >= 200 && status < 300) {
    	alert('success');
    }

Meanwhile, Bob has updated and merged his branch-bob into the master branch. He’s done for the day!

Unfortunately for John, he can’t merge branch-john with the master branch anymore, as there is now a merge conflict. This is because his commit was trying to modify the same line of code as Bob’s did on the original codebase, and Git couldn’t help automatically merge the commits.

$ git merge branch-john

Auto-merging example.js
CONFLICT (content): Merge conflict in example.js
Automatic merge failed; fix conflicts and then commit the result.

The above output occurs when John tries to merge his branch with the updated master branch. Here’s when we resolve the conflicts ourselves.

Basic conflict resolution with the command line

  1. Launch the Terminal (on macOS or Linux) or Git Bash (on Windows) if necessary.
  2. Navigate using cd DIRECTORY_NAME until you reach your repository root folder. Use ls to list the contents of the current directory if needed.
  3. Now, assuming you have attempted a merge but have failed, check which files have a conflict using git status. You should see something like the following:
$ git status

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 ..." to mark resolution)
        both modified: example.js
 
no changes added to commit (use "git add" and/or "git commit -a")
  1. Open the file with conflicts (in this case example.js, notice how it says both modified) using a command line text editor like vim, or with a GUI text editor of your choice.
  2. Look for the <<<<<<<, =======, >>>>>>> conflict markers, which marks the conflicting changes from the current master branch (HEAD) and John’s branch respectively, separated by the ======= marker. In John’s case, he would see something like the following:
    <<<<<<< HEAD
    if (status == 200 && completed) {
    =======
    if (status >= 200 && status < 300) {
    >>>>>>> john
        alert("success")
    }
  3. Manually merge the changes by modifying the file, considering whether to keep only the original branch’s code, your branch’s code, or rewriting a new change based on both. Remove the <<<<<<<, =======, >>>>>>> markers in the process. John can thus modify the code to the following to resolve the issue.
    if (status >= 200 && status < 300 && completed) {
    	alert('success');
    }
  4. Add or stage your changes, e.g. with git add ., then commit and push with a reasonable merge commit message by running git commit and git push.

Alternative: Using a git merge tool

You can use other tools or software to help you in visualising a merge. You can cd into the repository root directory similar to the above, and run git mergetool. This would allow you to use a merging utility like opendiff and step you through the merging process, which can be through a GUI rather than the CLI.

There’re many different tools out there and thus instructions for each may differ. The basic idea is the same: you have changes from two branches, manually determine which to keep and discard, or rewrite, then commit your merge. A GUI merge tool can help easily visualise the changes. Meld is one that I can recommend, it’s open source and is simple to use.

Conclusion

I hope this gives you a better idea of how to resolve merge conflicts. Feel free to ask any questions in the comments section below, I’d be happy to help! The references below were used in writing this article, and it may also be helpful to you.

References

Comments