Resolving merge conflicts in Git
Two ways git merge/git pull can fail
There are 2 ways in which git merge (or a git pull, which is a git fetch and then a git merge) can fail:
Git can fail to start the merge
This occurs because git knows there are changes in either your working directory or staging area that could be written over by the files that you are merging in. The error message is as follows:
error: Entry '<fileName>' not uptodate. Cannot merge. (Changes in working directory)
or
error: Entry '<fileName>' would be overwritten by merge. Cannot merge. (Changes in staging area)
Git can fail during the merge
This occurs because you have committed changes that are in conflict with someone else's committed changes. The error message is as follows:
CONFLICT (content): Merge conflict in <fileName> Automatic merge failed; fix conflicts and then commit the result.
Common questions for when git fails during the merge
How do I know which files have conflicts in them?
If your merge failed to even start, there will be no conflicts in files. If git finds conflicts during the merge, it will list all files that have conflicts. You can also check on which files have merge conflicts by doing a 'git status'.
Example:
# Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: <Some file> # # Changed but not updated: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # unmerged: <file> #
"Changes to be committed": All committed changes to files that are not affected by the conflict are staged.
"Changes but not updated": All files that have conflicts that must be resolved before repository will be back to working order.
How do I find conflicts within the file itself?
Conflicts are marked in a file with clear line breaks
<<<<<<< HEAD:mergetest This is my third line ======= This is a fourth line I am adding >>>>>>> 4e2b407f501b68f8588aa645acafffa0224b9b78:mergetest
<<<<<<<: Indicates the start of the lines that had a merge conflict. The first set of lines are the lines from the file that you were trying to merge the changes into
=======: Indicates the break point used for comparison. Breaks up changes that user has committed (above) to changes coming from merge (below) to visually see the differences.
>>>>>>>: Indicates the end of the lines that had a merge conflict.
How do I resolve a merge conflict in a file?
You resolve a conflict by editing the file to manually merge the parts of the file that git had trouble merging. This may mean discarding either your changes or someone else's or doing a mix of the two. You will also need to delete the '<<<<<<<', '=======', and '>>>>>>>' in the file.
What do I do after I've resolved conflicts in all affected files?
git add the file(s), git commit and git push
Tools to help you resolve both types of merge conflicts
The following git tools below can help you resolve both simple and more complicated git merges.
General tools
git diff
A command that helps find differences between states of a repository/files. Useful in predicting and preventing merge conflicts.
git diff origin/master <fileName>: Find the differences between the current index (HEAD) of fileName and what is in the central repository (origin/msater)
diff --git a/mergetest b/mergetest index 9be56b9..0aeffac 100644 --- a/mergetest +++ b/mergetest @@ -1,3 +1,4 @@ hello +I am also editing this line This is a test -This is my third line +This is a fourth line I am adding
Changes coming from origin/master are marked with +, while changes that are in your local repository (HEAD) are marked with -. This syntax does not notify which lines are added are deleted but just which lines originate in which state of the file.
git diff FETCH_HEAD <fileName>: Will provide the same output as above except is limited to the index of the last fetch that the user did. This may not be latest revision in the central repository.
git status
The git status command provides an overview of all files that have been modified and are in conflict at the time of the merge.
Example:
# Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: <Some file> # # Changed but not updated: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # unmerged: <file> #
- "Changes to be committed": All changes to files that are not affected by the conflict are staged.
- "Changes but not updated": All files that have conflicts that must be resolved before repository will be back to working order.
Tools specifically for when git refuses to start merge
git stash
IMPORTANT: Do not use git stash if git went through with the merge and there were merge conflicts! Only use git stash if git refused to merge because it foresees there being conflicts.
Stashes away any changes in your staging area and working directory. This command is useful in saving all changes not ready to be committed and the user wants to have an updated repository.
git stash save "<Save Message>": Save changes to files in working directory and staging area that git is aware of
git stash save "Saved changes for stash example" Saved working directory and index state "On master: Saved changes for stash example" HEAD is now at 4e2b407 Added second file for example.
git stash list: List the stashes that you currently saved
git stash list stash@{0}: On master: Saved changes for stash example
git stash pop <stash@{#}>: Removes the most recent stash or any stash specified and applies changes as a merge. If merge fails the stash is not removed from the list and must be removed manually.
git stash apply <stash@{#}>: Applies changes of recent stash or any stash is list specified, but doesn't remove it from the list.
git stash drop <stash@{#}>: Removes the most recent stash or any stash specified from the list.
git stash clear: Removes all stash's stored in the list
git checkout
git checkout <fileName>: Useful to reset your local working directory with the most updated version of the file in your index. Use to trash any local (non-committed or staged changes) to perform a git pull
Tools specifically for when git conflicts arise during a merge
git reset
Reset repository in order to back out of merge conflict situation. git reset, particularly with the --hard option can be used to back out of merge conflict (click here and here for more information).
IMPORTANT: Do not use any other options other than --hard for reset, as they will leave conflict line markers in file and you can end up committing files with conflict markers still present.
Scenarios
Git refuses to start a merge/pull
Error Messages:
error: Entry '<fileName>' not uptodate. Cannot merge. (Changes in working directory)
error: Entry '<fileName>' would be overwritten by merge. Cannot merge. (Changes staged, but not commited)
Steps toward Resolution:
- git stash save "<Message that describes what is being Saved>" (Stashes away any changes in your staging area and working directory in a separate index.)
- git status (Verify all changes are staged)
- git pull or git merge (Bring in changes from central repository or another branch)
- git stash pop (Will repopulate your changes into your working directory, may have to resolve merge conflicts)
Git is unable to resolve a merge/pull
Error Message:
CONFLICT (content): Merge conflict in <fileName> Automatic merge failed; fix conflicts and then commit the result.
Steps toward Resolution:
- git status (Shows all files that are in conflict as unmerged changed in working directory.)
- Resolve Merge confilicts
- git add <files>
- git commit -m "<Informative commit message>"