How do I deal with conflicts in my Git repo?
What is a conflict and when do they occur?
A conflict occurs when you ask Git to merge two versions of a file and it can’t figure out which version to pick. This often happens when you are trying to merge one branch into another (including git pulls). If you change code on the same line in the same file in two different branches, attempting to merge the branches will result in a conflict.
What exactly does it mean to resolve a conflict?
When Git asks you to resolve a conflict, it is saying:
I have two sets of changes for this file and they touch the same lines of code … I’m not sure which one to pick and I can’t merge them automagically. Help me decide!
You are then given a list of files that you need to review. Depending on your Git client it may look like this:
Or, if you use the command line, it can look like this:
In the example above, we tried to merge a branch called “new-branch” into a branch called “master”. Git has interrupted our merge with the message about unresolved conflicts. In this particular case we have conflicts in two files: index.html and LICENSE. To resolve this conflict and complete our merge we will have to update each file by hand.
Tip: What if you don’t have the time or desire to deal with a conflict in the moment? Abort the merge and revert to the state the repo was before you attempted the merge. In Tower, you can use the Abort button (visible right above the conflict message). In the command line you can use “git reset --merge” command.
How do you resolve a conflict?
To resolve the conflicts you will have to open both files in your text editor of choice. When you open a file that has a conflict, you will see something like this:
You can see that Git has added content (the less than and greater than signs, along with the branch name) to the file that were not there before we attempted the merge. This happened because we changed the same line of the code in both branches, and Git is not sure which one is the right one. Master includes the text “Birds”, while new-branch includes “Horses”. Neither one is incorrect, they are just different. And that’s why a human needs to make this decision.
Your goal here is to pick a version of code that is right for your project. You will have to edit this file to remove angular brackets and the incorrect version of the code. When you’re done you will tell Git to "add" this file, which means that you're done resolving conflicts in it.
Let’s go with the “Horses” version of the text. We can remove the “Birds” version and cleanup the text that Git has added to make sure they don’t break the HTML syntax. The final result will look like this:
We have resolved our first conflict! Now that you know what conflicts are and how to resolve them, let’s talk a little about why they are important and what can go wrong.
Incorrect conflict resolution can lead to file corruption and loss of changes
As you have just seen, when a conflict exists, Git changes the contents of your files to add special conflict notations (again, the less than and greater than signs). If you ignore Git’s notification and commit files without resolving the conflicts, you may cause a problem. Often, you end up with files that include the content added by Git, which causes rendering issues for your site or application. Imagine your PHP script with a random set of greater than or less than signs included? It will likely break your application when deployed to your staging or production environment.
Consider another possibility. Imagine you have a conflict in a file and attempted to resolve it, but picked a wrong version of the code. When this happens you could revert changes that someone else was working on. There is no easy way to bring these changes back. When resolving a conflict you have to pick the version that you wish to keep with wisdom and discretion.
For these reasons and more, it's important to pay close attention when Git informs you that conflicts exist and to resolve them correctly.
Dealing with "deleted by us" and "deleted by them" conflicts
For some conflict notifications, Git will include a "Deleted by us" or "Deleted by them" message next to a file. That means that you modified a file in one branch and deleted it in another. Git has no way of knowing if you want to delete the file or modify it, so you need to make the choice yourself.
Dealing with this type of conflict is straightforward: you have to decide if the deleted file is still required. You can do that by opening the file and looking at its contents. If you want to keep the file deleted, use the "rm” command (for the command line). Otherwise, use the "add” command to restore the file. This will resolve the conflict for that file.
Tips for decreasing your chances of generating conflicts in Git
There are several things that you can do to decrease the number of conflicts that can occur while you’re using Git. If you see conflicts on a daily basis in your repo, your development workflow may require a few tweaks.
Here are a few recommendations:
- Keep every feature or bug fix in a separate branch.
- Keep your local repository up to date. Make regular pulls from the remote to ensure that your local repository has all the recent commits from your team.
- If you’re working in a branch, merge stable into it at least once a day.
- Instead of infrequent commits with a large number of changes, do regular small commits often.
- Each commit should address a single particular part of the bigger project you’re working on.
- Push commits to the remote right after you made them. In other words, don’t hoard commits in your local repo.