One of the most challenging yet common activities development teams run into with Git is resolving merge conflicts. This happens when multiple developers are making changes in a repository at the same time.
This post provides a walkthrough of how to get through two typical Git conflict scenarios. To set the scene, Grant and I are two developers working on a simple web page. We’re starting out with two files, index.html and styles.css. Our repository is hosted at GitHub, and in this case we are both working directly on the master branch.
Here are the two files at the beginning of the day.
SCENARIO 1: PUSHING COMMITTED CHANGES
I am making some changes to the text on index.html.
I commit my changes.
Then I try to push them.
Hmm. Something went wrong. Apparently another developer has made changes to the master branch since I last pulled.
In fact, my coworker Grant has pushed some styling changes. He added CSS classes to index.html and some rules to styles.css.
In order for Git to let me push my changes, I first need to pull down his changes so that my code is in sync with what’s out on GitHub. So I’ll run a git pull.
That partially worked, but it’s telling me there was a conflict. What happened here?
Git tries to reconcile Grant’s changes with the changes I just made. Some of them it can figure out and handle automatically. For example, the file styles.css was changed by Grant but not by me so Git just includes Grant’s change. It is also able to handle Grant’s addition of the “footer” class. It’s clever enough to see that this change was on a different line of index.html from my changes so it can bring it in without difficulty.
However, there was one change that Git could not figure out by itself. Grant and I both made changes to the <h1> line. Git informs me that I need to resolve this conflict manually.
If I do a git status, I can see the files that need to be manually fixed in the “Unmerged paths” section. Since Git was able to handle styles.css by itself, that’s already in the “Changes to be committed” section.
So how do I fix this conflict? I need to open the conflicted file manually. Here’s index.html in a text editor.
Indeed, Git added Grant’s “footer” class is there. No problem. But what’s this around the <h1> tag? Here’s where I need to do some manual conflict resolution. Git has included both Grant’s and my versions of the <h1> line. The top one is my version. It is labeled “HEAD”, meaning that’s what was on my system when I did the git pull. The bottom version is Grant’s. It’s labelled with the ID of Grant’s commit.
It is now my job to choose either my version or Grant’s version or some combination of the two. In this case, I want to combine them. I need to replace the entire section from <<<<<<< to >>>>>>> with the correct end result. Then I save the file and return to the command prompt.
All that’s left is to inform Git that I have finished fixing the conflict. git status tells me the command to run: git add index.html
Finally, I commit to finish the merge: git commit. This opens an auto generated merge commit message for me to confirm or edit. I’m happy with the message so I save and quit the message editor. Now I can push my changes.
Success!
Scenario 2: Pulling with uncommitted changes
Next I start playing around with the wording of the header. I start to make some local changes, “Mergerific”!
Grant tells me he has another important change that I should pull down. So I try a git pull.
Well that didn’t work. Git doesn’t want to pull down Grant’s change because it will overwrite the change I have locally. It says I need to commit my change first. If I do commit, I would then be able to merge Grant’s change as I did in scenario 1 above. But in this case, I’m not ready to commit my change. I’m still working on finding the wording I like.
Happily, Git has a solution for me: git stash. With this command all my local changes are temporarily removed but stored safely out of the way by Git.
Now I can pull down Grant’s changes.
And I can un-stash my changes.
When I un-stash, Git tries to merge my changes just like it did in scenario 1. In this case, I ran into a similar conflict on the header line.
I resolve it the same way, by opening index.html in an editor and replacing the <<<<<<< to >>>>>>> section.
In this case the changes I had stashed earlier are on the bottom. I resolve it and save the file.
That’s all there is to it. At this point I can add and commit the file whenever my changes are ready.
References For Further Reading:
Git Branching – Basic Branching and Merging
Git Tools – Stashing and Cleaning
Are you interested in learning more about resolving Git conflicts from the command line? Our 10-week coding bootcamps provide daytime instruction, helping you become an entry-level developer. We’ll teach you all about Git alongside in-demand programming languages.