Got a merge conflict & now you’re in Vim? Don’t panic, here’s what that means & what you can do to resolve it.
Learning how to use version control can be hella frustrating; especially if you do not work in a role that requires you to use a version control system (VCS) like Git on a daily basis.
In this blog post I am going to show you how to solve a merge conflict.
First we will look at what a merge conflict is and why they occur. Then we will cover three ways to resolve them using the Web UI (which stands for User Interface) on GitHub, the Command Line and the GitHub Desktop App.
First Things First, Merge Conflicts — What Are They?
Merge conflicts may occur if competing changes are made to the same line of a file or when a file is deleted that another person is attempting to edit. — help.github.com
OK… so what does that mean?
When we edit files within a repository (repository: think regular folder with a super smart .git file that tracks all your changes), we can make changes that won’t cause a merge conflict.
For example, if you add lines of code (or any text) to the end of a file; Git can recognise that you haven’t changed any of the existing content. So when you go to combine two versions of that file (or “merge” them), it will do so quite happily. Regardless of whether that merge is performed through merging your changes with a remote version of that repository on GitHub or merging your current branch back into the master branch on your local repository.
Merge conflicts occur when the changes are a little more complex.
Remember that computers are not the smartest of creatures, you have to tell them explicitly what you want, or they panic. So in this instance, if we go into our file and change one of the existing lines of code or text and try to complete a merge (of any kind), Git will have a tiny panic.
But you don’t need to worry, as Git can resolve these conflicts perfectly fine; it sends these warnings as a way to let you know that it needs more information about the changes you want to make. It is one of the many points in Git that allows you to “check yourself before you wreck yourself” and this is when we need to use one of the following methods to resolve the conflict.
Method 1 :: Using the WEB UI on GitHub
In my intro to Git workshops, I teach how to resolve merge conflicts to people by using a single text file in a repository. As an exercise, this covers several of the things that as a beginner I found totally baffling. I have no shame in admitting that it took me almost a year from creating a GitHub account to making my first pull request.
So let’s see how using the GitHub web UI goes:
For this example I created a repository on the web UI using the create a new repository option from the homepage of GitHub.
Then I forked this(made a copy of the entire repository) to my GitHub organisation My Kind Of. As a result you’ll see two versions of the repo exist, one at github.com/redroxprojects/medium-merge-conflict and one at github.com/my-kind-of/medium-merge-conflict.
I then made changes to both of the repositories by editing the README.md document — these changes were made on exactly the same line on both files but say different things, so the repositories are now out of sync with each other (which we know will cause a conflict).
After this, I made a pull request from the organisation fork to my original repository using the Pull Request tab.
And hitting this button:
If you don’t see the options for choosing base and head fork, here you may need to hit the “compare across forks” link (highlighted in blue in the image below).
Once the pull request is made we can start handling our merge conflict on the web UI.
Step one: Review the Pull Request!
Navigate to the ‘Pull requests’ tab in the original repository and open the pull request review section by clicking on the pull request.
In this case that is my redroxprojects/medium-merge-conflict repository.
Here you will see that there is a warning about the merge conflict and that the conflict must be resolved before we can complete the merge.
Step two: Resolve the Conflict!
Start by hitting the button that says “Resolve Conflicts”.
Then you will be taken to a new editor screen that looks like this:
You’ll see that is has the content of our README.md documents from both versions of this repository.
Additionally it has some new markers, in the form of less than <<<, equals === and greater than >>>> symbols, that separate the content.
In this example everything above the equals sign is from the original repository master branch, everything below is from the My Kind Of fork master branch.
Now what we do is delete the content we don’t want, or make any other edits that will correct the conflict. When we are finished, we need to delete those symbols to be able to mark this as resolved. When we hit that button you’ll see that the merge can now take place.
The editor will now have turned some parts green to show that we can go ahead and commit this merge. 🎉
Step three: Make the Merge!
When we hit the “commit merge” button, this will take us back to our Pull Request review screen. The box that was previously highlighted grey and informed us of our merge conflict, will now be highlighted green and have a green button asking us to “Merge pull request”.
This is where you get to hit that button!
It will ask you to confirm (another check yourself feature) and you can add any messages here about the merge if you wish to do so.
Now all the icons related to the merge will be purple and a purple icon saying “Merged” will appear at the top of the Pull Request review page.
Phew — conflict resolved! 😅
Method 2 :: Using the Command Line
Using the command line is always a little more hairy in my opinion. But it doesn’t have to be!
First things first, we should configure the tools we will use for the job. There is some really helpful advice on the Git Documentation Website about how to setup your config files.
In Git we can configure things on our local machines about our identity (username, email) and our editor (which text editor we want to use for entering messages). If you are like me and a mac user who is not interested in learning the eccentricities of vim as a text editor — then you will want to setup your editor in the config files.
FYI to quit vim you can hit ESC , followed by : , then q!
(ps. the exclamation point is part of the instruction and not just there because you will be happy to be free from vim ✨)
There is a nice resource on github.com for how to change your core editor to your text editor of choice.
So once you have configured the things, here is how a merge conflict will work:
For this example, I am going to clone the repository that I created in the web UI from github.com/redroxprojects/medium-merge-conflict.
This can be done using this command:
git clone https://github.com/RedRoxProjects/medium-merge-conflict.git
Just make sure you are in the location where you want the repository to end up. This command will create a new directory (folder) containing all of the contents of the online repository and the history of that repository.
Then to cause the conflicts we will make some changes to the same README.md document using a text editor locally. Like so:
And some changes to the online version of that README.md using the edit file button. Like so:
Once the changes are committed on both versions, we can start the process of resolving the merge conflict.
Step one: Start Your Merge
On this occasion we will use the
git pull command, which in essence performs a
fetch and a
merge all in one.
This is most common place to encounter merge conflicts as a beginner with Git. It is certainly where I came across one for the first time!
As with a lot of programming concepts and practices, you learn more about these from doing — so do not feel bad if this is your first time seeing this on the command line and it looks overwhelming (that’s perfectly normal).
Now if you haven’t configured your editor you might end up being thrown into a vim window here. Don’t panic you can just quit this and the elements of the merge conflict will show up in your text editor when you open the file that has the conflicts.
So here is what happens when we run this command:
Not very eventful right?
Step Two: Resolve the Conflict!
Git has told us what we need to do next in the output of the pull command:
fix conflicts and then commit the result
But unless your fluent in Git-ish then this isn’t exactly a straight forward instruction. You need to know where the conflicts are as starting point — which Git also helpfully tells us.
What we need to do now is navigate to the file that is causing us an issue, we know from the output of the pull command above that this is the README.md.
By opening the README.md file in a text editor we can see the elements of the merge conflict.
Again we have some new markers, in the form of less than <<<, equals === and greater than >>>> symbols, that separate the content.
In this example everything above the equals sign is from the local commit, everything below is from the last commit on the remote repository master branch (we even get a reference here of the hash for the commit).
What we need to do now is choose what we want to keep and what we want to delete; again don’t forget to remove all those lovely markers (and the word HEAD and that hash).
Step Three: Commit the Changes!
Once we have made our changes, we can use
git add README.md and
git commit -m “[commit message]" to create a new commit with our changes. Don’t forget to make your message meaningful to you (future you will be thankful if you ever need to move back through the commit history).
Once we have resolved this, it is good practice to push our changes to ensure everything on the remote is up to date with this resolution. We do this using the
git push command which will update the remote with the last commit (the one in which we resolved the merge conflict).
Your repository will then be up to date and when you check with
git status everything should be hunky-dory.
Le Sigh — conflict successfully avoided! 🙌
Method 3 :: Using the GitHub Desktop App
Ok so what if you don’t use the online platform or the command line but you want to add version control to your workflow.
Well if this is you… you can use the GitHub Desktop App.
This is available for macOS and windows at present, follow this link for the GitHub help pages on how to install and configure GitHub Desktop for your machine.
This lets you view your changes, history and branches all within a helpful desktop window.
Here’s what you see once you have logged in:
You can then navigate repositories by choosing to clone one from GitHub, publishing an existing project or create one from new.
There are some really nice guides on the GitHub help pages that will give you what you need to start using this tool.
A Note About Merging in the Desktop App.
*As explained in the intro to this post, the Desktop App does not handle merge conflicts inside of the application.
Merging within the Desktop App occurs across branches — we don’t have the same pull/push mechanism as we do on the command line; anything related to remotes will send you to the web UI to create a pull request.
However you can still merge branches using the app, so let’s look at what happens when we create a merge conflict doing that.
Step One: Create a Conflict…
For the example using the Desktop UI I created a new project called merge-conflicts using the create a new repository menu (left).
Once I had the repository I created a file called hello.md within the merge-conflicts folder located in my documents file.
I added some text and then created a new branch using the menu within the Desktop app. Now normally branches are named after their purpose (e.g. the name of a feature, or bug-fix, or testing method).
However as this is just for fun, I named my branch
branchymcbranchface (I instantly regretted this). So as you can see from the image below — we now have two branches in the merge-conflict repository.
Now all we need to do is edit the same line, within the same file, on both branches. I did this by adding the word ‘banana’ at the end of the hello.md document on the master branch and the word ‘orange’ in the same place in the hello.md document on the branchymcbranchface branch.
Step Two: Use the Desktop App to Try to Merge the Branches
You’ll find the option to do this in Branch sub-menu of the top menu bar of the application.
Or as it suggests you can use the keyboard shortcut:
SHIFT + ⌘ + M.
Now when you do this make sure you are currently on the branch that you wish to merge the changes into.
When we select this option to merge branchymcbranchface into master in the merge-conflicts repo. We are greeted with an entirely expected error message, this is what you will see if you create a merge conflict that the Desktop App cannot merge automatically.
Now we can get to work on resolving those conflicts!
Step Three: Resolve the conflict!
When we navigate back to our hello.md document in our text editor, we will see the elements of the conflict (like we do when using the command line).
Again we have some new markers, in the form of less than <<<, equals === and greater than >>>> symbols, that separate the content.
These changes in the Desktop App appear like this:
Going back to our text editor, we can delete what we don’t want and keep what we do; again we need to remove the markings and branch names after doing this.
Then, we can add a description and hit the commit to master button. This will create a new commit merging the content of the two branches.
And there you have it — conflict resolved!
That’s All Folks
Thanks for reading my post; if you’re still baffled by any of this, feel free to contact me — I am always happy to help! (Twitter is the best place to find me for this)
Additionally, in my role as GitHub Campus Expert, you’ll find me giving workshops all over the UK — feel free to contact me if you want help providing Git & GitHub workshops for your community. My profile and details for this can be found on the GitHub Campus Expert Website.