When merging branches, three different types of conflicts may arise
- The same line of code was changed in different ways in the two merging branches.
- A file was changed in one branch but deleted in the other branch.
- The same file is added in different branches, but the content of the file is different in the two branches.
Whenever there's a conflict Git will not know how to merge the branches and it's going to ask us to solve the conflicts manually before staging and committing the merge.
To see an example of the first scenario, let's create a new branch called bugfix and change the toc.txt file. In this file, we'll delete all its content and on the first line write Changes from bugfix branch. Now stage it and commit it.
Next, we'll switch back to master. Open the toc.txt file. Delete all its content, and in the first row write Changes from master branch. Stage it. Commit it.
Now we'll run
git merge bugfix
Now Git is telling us that there is a conflict and that the automatic merge process failed. Notice that Git Bash has changed from master to master|MERGING. This tells us that Git is in the middle of a merge process.
First, let's run
git status
Here we can see where the merge conflict is under the unmerged paths. Git is telling us that both branches have changes to toc.txt. So let's open toc.txt in VS Code by running
code toc.txt
The image to the right is what you'll see in VS Code. What we see are markers that represent the changes in the current branch (green) and the changes in the other branch (blue). In between them there's a divider marked by equal signs, =======. This syntax will be repeated throughout the file as many times as there are conflicts.
On top of the HEAD marker, there are three buttons. We need to choose one. If we select Accept Current Change then the changes from the current branch will be kept and the incoming ones will be discarded. If the select Accept Incoming Changes the incoming changes will be kept and the current ones will be discarded. If we select Accept Both Changes then both changes will be kept, in the order in which VS Code is showing them.
For this demo, I'll go with Accept Both Changes and the file will change to what you see on the image to the left.
Three brief comments before we move on. There's a fourth button that reads Compare Changes. If you click on it, VS Code will open the file in diff mode (that is, showing the changes side by side).
If you selected an option and wish to change it, even if you have already saved it, just press Ctrl + z (undo). Git will not continue with the merge process until we manually create a merge commit.
You can always edit the file by hand. To do so, you'll need to remove the markers and the separation. Try not to include new changes on the merge commit (that is, new code or new lines of any sort). But sometimes this is not possible because of the kind of merge conflict that we are faced with. We refer to merge commits that add new code as evil commits.
Now that we have resolved all merge conflicts, we can stage our changes with git add toc.txt. If we run
git status
we'll see that now there are no more unmerged paths. Therefore, there are no more changes. At this point, we can commit our changes. Since this is a merge commit, we will not introduce a commit message. So we run
git commit
Because we didn't provide a commit message, Git will open VS Code. In general, we accept the default short-message but add a description explaining how the merge conflicts were resolved. Once done, we save our changes and close VS Code. Now Git will complete the merge process. You can see that Git Bash has changed from master|MERGING to master.