Fixing merge conflicts in Git
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:
Bob has implemented some validation and modifies the code in branch
bob
:if (status == 200 && completed) { alert('success'); }
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
- Launch the Terminal (on macOS or Linux) or Git Bash (on Windows) if necessary.
- Navigate using
cd DIRECTORY_NAME
until you reach your repository root folder. Usels
to list the contents of the current directory if needed. - 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")
- Open the file with conflicts (in this case
example.js
, notice how it says both modified) using a command line text editor likevim
, or with a GUI text editor of your choice. - 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") }
- 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'); }
- Add or stage your changes, e.g. with
git add .
, then commit and push with a reasonable merge commit message by runninggit commit
andgit 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.