Resolving Git Merge Conflicts
Tags: git, webdev, beginners, programming
Published: 2022-10-23 18:53:15

Merge conflicts are often a part of life for working on complex development projects. In this guide we'll look at how you can deal with them, and when they will occur.

## When do merge conflicts occur?

A merge conflict in Git will occur if you have made changes to the same file on a the branch you are on, and the one you are trying to merge into. In this case, Git won't know which one should be used - so it will throw a merge conflict error. 

Consider the scenario where a change has been made to `file.md` in the `main` branch and `my-branch`. When we checkout `main` and try to merge `my-branch` into `main`, we will run into the following error:
```shell
git merge my-branch

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

Git doesn't know what to do here, so it's our job to try and resolve it.

## Stabilizing the current branch
Sometimes, when we try to merge a file, the merge will fail completely:
```shell
error: Your local changes to the following files would be overwritten by merge:
        file.md
Please commit your changes or stash them before you merge.
```

This happens because we have uncommitted changes on our current branch. We need to close all changes on our current branch before we can merge. To do that, you can run `git stash` ([I covered git stash in more detail here](https://fjolt.com/article/git-mastering-stash)), or you can simply commit your changes on this branch to stabilize it:
```shell
git add -A
git commit -m "My commit message"
```

Now that our branch is stabilised, we can try to run `git merge my-branch` (where `my-branch` is your branch) to merge our branch back into `main`. If we run into merge conflicts now, we need to resolve them.

## How to resolve merge conflicts in git via GUI

If you're using a modern code editor like Visual Studio Code, then merge conflicts will appear in the GUI where you can accept incoming changes or accept the current changes on your branch. This provides a pretty easy way to fix your conflicts. In Visual Studio Code, this is represented in conflicting files via the GUI shown below. You have a number of options:
- "Accept Current Changes" - this will use your current branch's content.
- "Accept Incoming Changes" - this will use the content from the branch you are merging in.
- "Accept Both Changes" - this will keep both, one under the other.
- "Compare Changes" - this will bring up an additional screen to compare changes side by side.

![Resolving Git Merge Conflicts via Visual Studio Code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zham1w82oa234lqogm24.png)

Once you review all conflicts, you can then add your files and commit them as normal:
```shell
git add -A
git commit -m "My commit message"
```

### How to resolve merge conflicts in git via Terminal
In some cases, you may not have a GUI to resolve merge conflicts. There are a number of commands you can use.

**First**, `git status` will tell you the files affected:
```shell
git status
On branch my-branch
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:   file.md

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

As we can see, only `file.md` is affected. Next, we can use `git diff` to see the difference between this branch and the one we are merging into:
```
++<<<<<<< HEAD
 +Some  a
 +Some b
 +Some conflict c 
 +Some conflict d
 +Some e
++=======
+ Some conflict 1
+ Some b
+ Some conflict c
+ Some conflict 2
 -Some f
++Some f
++>>>>>>> main
```

Here, everything after `++<<<<<<<` and before `++=======` represents the current branch changes, while anything after `++=======` and before `++>>>>>>> main` represents the branch you are merging in. 

We can also see the conflicting commits by running `git log --merge`

### Aborting your merge during a merge conflict
Sometimes you realise you're in a bit too deep on this merge conflict - in which case you can undo it by running `git merge --abort`.
```shell
git merge --abort
```
This will bring us back to a non-merge state so we can resolve merge conflicts manually in both branches, before trying to merge again.

### Resolving by accepting incoming or current changes
Another easy way to resolve merge conflicts on certain files is to use the `--theirs` and `--ours` option on `git checkout`. Our merge conflict was on `file.md`. If I want to accept all incoming changes for `file.md` from the branch I am trying to merge, I could write:
```shell
git checkout --theirs file.md
```

This checks out the `file.md` from "their" version of code. If I wanted to use the version in my current branch, I'd use `--ours`. Both `--ours` and `--theirs` expects a file as an argument - so this has to be done on a file by file basis.

Easy, right? That's fine for merging in entire files, but what if we have multiple merge conflicts within a file?

### Resolving by editing the file itself
Remember, when you create a git merge conflict, we ended up with content that looked like this when we ran `git diff`?
```shell
++<<<<<<< HEAD
 +Some  a
 +Some b
 +Some conflict c 
 +Some conflict d
 +Some e
++=======
+ Some conflict 1
+ Some b
+ Some conflict c
+ Some conflict 2
 -Some f
++Some f
++>>>>>>> main
```

That content also **exists** in your file where the conflict happens (without the `+` and `-`, of course). The easiest way to resolve a merge conflict when you want to do it without any help from a GUI is to go to the file in question, and simply remove the section you don't want to accept. That just means deleting the text between `<<<<<<< HEAD` and `=======` if you want to accept current, or the text between `=======` and `>>>>>>>` if you want to accept incoming.

### Adding and commiting your changes
Once you've resolved your merge conflicts, don't forget to add and commit your changes on the current branch, so they remain saved:
```shell
git add -A
git commit -m "Merge message"
```

## Conclusion
We have powerful tools in our code editors to resolve merge conflicts. Having said that, sometimes limitations in environments mean we have to resolve our own git merge errors - or we may just prefer doing this work from terminal. Some specific edge cases may also mean we have to do this work from terminal. 

In any case, merge conflicts are a part of development with git, and they can be resolved simply by removing the content we don't want anymore from the files where the conflicts exist. We can also use `git checkout --theirs` or `git checkout --ours` to resolve issues more quickly.