Introduction
The git merge
command helps a contributor add to a project from a branch. When multiple contributors work on the same part of a code or work with numerous branches, merge conflicts often happen. The primary goal of git merge
is to resolve or warn about these conflicts automatically.
This guide explains what a merge conflict is, how to prevent one, and offers resolutions for when they do not sort out automatically.
Prerequisites
- Git installed and configured (on Windows, Mac, or Ubuntu).
- A
git merge
conflict between a local and remote branch. - A text editor such as Vim or nano.
What Is a Git Merge Conflict?
When working with version control systems such as Git, most merge conflicts resolve automatically. However, there are situations where git merge
is unable to resolve an issue.
Note: Check out our handy Git commands cheat sheet, which features commonly used commands such as git merge
.
Some examples of merge conflicts include:
- Changing the same lines of code in a file.
- Removal of files while changes happen in another place.
Since the problem happens locally and the rest of the project members are unaware of the issue, resolving the conflict is of high priority and requires an immediate fix.
Types of Git Merge Conflicts
Merge conflicts occur when Git encounters discrepancies between two branches that cannot be automatically resolved. These conflicts typically arise in two main stages of the merge process: before the merge starts and during the merge itself.
The sections below explain the two main merge conflict types.
Conflict Before Merge
A conflict before a merge occurs when Git identifies changes in the working directory or staging area of the current project that could be overwritten by the commits being merged. These are not conflicts between branches but conflicts with local pending changes.
Git prevents the merge to ensure that no local modifications are unintentionally lost. Common causes include uncommitted changes or files that differ from their last committed state. When this happens, Git halts the process and outputs an error message similar to the one below:
error: Entry '<fileName>' not uptodate. Cannot merge. (Changes in working directory)
To resolve these conflicts, stabilize the local repository state using one of these methods:
- git stash. Temporarily save local changes and apply them later.
git checkout
. Discard changes in the working directory.git commit
. Save the changes to the repository.- git reset. Unstage changes from the index.
Once you resolve the issue locally, proceed with the merge.
Conflict During Merge
A conflict during a merge happens when Git detects discrepancies between the current local branch and the branch being merged. These conflicts are often caused by code changes made by different developers on the same file or lines of code. In such situations, Git cannot determine the correct resolution.
Git attempts to merge the branches automatically but leaves unresolved portions for manual intervention. It interrupts the merge process and outputs an error message like the one below:
error: Entry '<fileName>' would be overwritten by merge. Cannot merge. (Changes in staging area)
The possible solutions for addressing conflicts during a merge are:
- Inspect the conflicted files. Look for conflict markers (
<<<<<<<
,=======
,>>>>>>>
) within the affected files. - Manually resolve conflicts. Choose the appropriate code from each branch or rewrite the section.
- Mark conflicts as resolved. Use the
git add [file_name]
command to stage the resolved files. - Complete the merge. Finalize the process with
git commit
.
Note: Learn about the differences between git rebase and merge.
How to Identify Merge Conflicts in Git
Being able to identify merge conflicts in Git is essential to resolve issues and successfully merge branches. When a merge conflict occurs, Git provides clear indicators and commands to help you diagnose the problem.
When a conflict arises during a merge, Git outputs a descriptive message to alert you to the issue. This message typically appears in your terminal and includes details about the conflicted files. For instance, if you run the git status
command after a failed merge, you may see something similar to the message below:
$ git status
On branch main
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: merge.txt
The key point in this output is the unmerged paths section, which lists files with conflicts, such as merge.txt in this case.
To understand what caused the conflict, examine the affected files. Use the cat command or open the file in your preferred text editor to reveal conflict markers. For example:
$ cat merge.txt
<<<<<<< HEAD
content to be modified
content to append
=======
different content to be merged later
>>>>>>> new_branch_to_merge_later
The markers serve as conflict dividers and break the file into three sections:
<<<<<<< HEAD
- Content from the current branch (e.g.,main
) pointed to byHEAD
.=======
- The divider separating the conflicting sections.>>>>>>> new_branch_to_merge_later
- Content from the branch being merged (e.g.,new_branch_to_merge_later
).
How to Resolve Merge Conflicts in Git
There are three ways to resolve a merge conflict in Git:
1. Accept the local version. To accept all changes on a file from the local version, run:
git checkout --ours [file_name]
Alternatively, accept the local version for all conflicting files with:
git merge --strategy-option ours
2. Accept the remote version. To update the changes on a file from the remote branch, enter:
git checkout --theirs [file_name]
To accept the remote version for all conflicting files, use this command:
git merge --strategy-option theirs
3. Review changes individually. The final option is to review each change separately. This option is also the best path to take, especially when working with multiple files and people. To make this job more manageable, use special tools to help review individual conflicts.
Ultimately, the choice of which parts of the code stay and which don't depends on the developer's decision for the current project.
Getting a Merge Conflict in Git
The merge conflict in Git happens when the command git merge
throws an error.
The error message prints the information about where the conflict is present. Check the file from the error message and look at the contents where the merge conflict happened:
Git automatically adds three indicators alongside the conflicting lines of code:
<<<<<<<
(seven "less than" characters) followed byHEAD
, which is an alias for the current branch. The symbols indicate the beginning of the edits within this section.=======
(seven "equals sign" characters), which show the end of the revisions within the current branch and the beginning of the edits within a new one.>>>>>>>
(seven "greater than" characters) followed by the branch where the attempted merge happened. The added symbols indicate the ending of the edits within the conflicting branch.
The added syntax helps search through the code to find the location of the merge conflict. However, a much more straightforward approach is to use a difference/merging tool to discover the issues and track the changes.
Note: Learn how to combine multiple commits by squashing commits in Git.
Setting Up Default Diff Tool in Git
To set up the default diff tool for git mergetool
:
1. Run the following line in your terminal:
git mergetool --tool-help
The output prints out all the supported diff tools for your current setup:
Different tools are available based on the editor you are using. For example:
- Emacs diff tools: Ediff or emerge
- Vim diff tools: vimdiff, vimdiff2 or vimdiff3
The further steps show an example of how to set up the vimdiff tool for Vim.
2. Change the git config
to set the default merge tool:
git config merge.tool [tool_name]
For example, if you are using Vim, run:
git config merge.tool vimdiff
3. Set the diff tool to show the common ancestor for both files, which is the version before any edits:
git config merge.conflictstyle diff3
4. Set the option to not prompt before running:
git config mergetool.prompt false
The diff tool setup for Git is complete.
Using Mergetool to See the Differences
To use the mergetool
and see the differences, run:
git mergetool
The output displays a window with four views:
1. LOCAL represents the file version from the current branch.
2. BASE is how the file looked before any changes.
3. REMOTE shows how the file looks in the remote branch where the conflicting information is.
4. MERGED has the final merge file. This result represents what gets saved to the repository.
The primary navigation commands between these windows are:
- CTRL+WW to move between the windows.
- CTLR+WJ to jump to the MERGED window view.
- CTRL+WX to switch places of the windows.
For advanced navigation, information is available with the command:
:help window-moving
Updating and Resolving a Merge Conflict
Update the MERGED file to resolve a conflict. Some shortcuts for updating the MERGED version include:
- :diffg LOCAL updates to the LOCAL version.
- :diffg BASE updates to the BASE version.
- :diffg REMOTE updates to the REMOTE version.
Note: Ensure the cursor is on the line where the conflicts are before running these commands.
Once the information is updated, save and quit with :wqa
.
Commit and Cleanup
The final step is to commit and clean up the extra files. Commit the updated version by running:
git commit -m "<your message>"
Note: If you made a mistake while committing, you could undo the last commit.
The diff tool creates extra files on the project for comparing versions. Clean them up with:
git clean -f
Git Commands Used to Resolve Merge Conflicts
The commands used to resolve merge conflicts also ensure that your repository remains in a stable state throughout the process. Each command serves a specific purpose, from staging resolved changes to cleaning up temporary files.
The table below summarizes the key Git commands used to handle merge conflicts:
Command | Description |
---|---|
git stash | Temporarily save local changes and apply them later. |
git checkout --ours|--theirs [file_name] | Discard changes in the working directory or accept a specific version during conflict resolution. |
git commit -m "message" | Save changes to the repository. |
git reset | Unstage changes from the index. |
git merge | Merge branches and resolve conflicts. |
git merge --abort | Abort an in-progress merge process. |
git add [file_name] | Stage resolved files after resolving conflicts. |
git config merge.tool [tool_name] | Configure Git settings, such as the default merge tool or conflict style. |
git mergetool | Open the default merge tool to visualize and resolve conflicts. |
:diffg LOCAL | Update the merge file to the LOCAL version using Vimdiff. |
:diffg BASE | Update the merge file to the BASE version using Vimdiff. |
:diffg REMOTE | Update the merge file to the REMOTE version using Vimdiff. |
:wqa | Save and quit all windows in Vimdiff after resolving conflicts. |
git clean -f | Remove extra files created during conflict resolution. |
Tips On How to Prevent Merge Conflicts
Merge conflicts only happen when a system cannot resolve the problem automatically.
Here are some tips on how to prevent merge conflicts:
- Use a new file instead of an existing one whenever possible.
- Avoid adding changes at the end of the file.
- Push and pull changes as often as possible.
- Do not beautify code or organize imports on your own.
- Avoid the solo programmer mindset by keeping in mind the other people who are working on the same code.
Conclusion
Merge conflicts happen when working in Git or other version control programs from time to time. By following the instructions in this guide, you know how to handle merge conflicts and how to prevent them from happening.
For more Git resources, see how to set upstream branch in Git, or learn to use GitHub with our tutorial for beginners.