Merge conflicts occur when multiple authors edit the same content or when one developer deletes a file while another developer was making changes on it. To solve this problem developers work in isolated branches. The git merge command is responsible for combining isolated branches and resolving conflicting edits.
Git makes the merging process easier unlike most version control systems. Git even can automatically integrate new changes. But in the cases of conflicts, Git cannot automatically figure out what version is correct. It marks the file as being conflicted and stops the merging process.
Types of merge conflicts
Conflicts can arise at two points: at the start of the merge process or during it.
Merge failure on start
Git fails to start a merge because the pending changes in the working directory or staging area of the project should be written over by the commits being merged in. This happens because of pending local changes. To take control over the local state, the git stash, git checkout, git commit and git reset commands are used. The following message will show up when an error occurs on start:
error: Entry '<fileName>' not uptodate. Cannot merge. (Changes in working directory)
Failure during merge
The failure during merge tells that there is a conflict between the current local branch and the branch that is being merged in. The following message will show up when an error occurs during merge:
error: Entry '<fileName>' would be overwritten by merge. Cannot merge. (Changes in staging area)
Creating a merge conflict
Here, we will show you a simulation of how merge conflicts appear.
mkdir test-dir cd test-dir git init . echo "some content" > example.txt git add example.txt git commit -am "initial commit" [master (root-commit) a45c22d] initial commit 1 file changed, 1 insertion(+) create mode 100524 example.txt
In the given example, we create a test-dir new directory. Next, we create example.txt text file with some content and add it to the repository and commit it. As a result, we have a new repository with one master branch and example.txt file. The next step is creating another branch to use as a conflicting merge.
git checkout -b branch_to_merge echo "completely different content to merge later" > example.txt git commit -am "edit the content of example.txt to make a conflict" [branch_to_merge 4221135] edit the content of example.txt to make a conflict 1 file changed, 1 insertion(+), 1 deletion(-)
In the above example, we create and check out branch_to_merge branch. After creating, we overwrite the content in example.txt file and commit the new content. After doing all this, the commit overrides the content of example.txt:
git checkout master Switched to branch 'master' echo "content to add" >> example.txt git commit -am "added content to example.txt" [master 11ab34b] added content to example.txt 1 file changed, 1 insertion(+)
This bunch of commands checks out the master branch attaching the content to example.txt and committing it. So, our repository is put to the state where we have one commit in the master branch and one in the branch_to_merge branch. The final step is to execute the git merge command after which conflict will occur:
git merge branch_to_merge Auto-merging example.txt CONFLICT (content): Merge conflict in example.txt Automatic merge failed; fix conflicts and then commit the result.
Identifying merge conflicts
As we have already seen, Git displays output which indicates that a conflict has appeared. Execute the git status command to see the unmerged paths:
git status On branch master 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: example.txt
The example.txt file appears in a modified state. Execute cat command to put out the contents of the example.txt file. We can see these visual marks:
<<<<<<< HEAD ======= >>>>>>> branch_to_merge
The ======= marks is the center of the conflict. The content between the center and the HEAD line is the content existing in the current branch master that the HEAD reference is pointing to. Read more about visual marks on the git merge page.
Resolving merge conflicts
To resolve a merge conflict you should edit the conflicted file. Open the example.txt file in the editor and remove all the marks. The changed file has the following look:
some content to mess with content to add completely different content to merge later
Execute the git add the command to stage the new merge content. Next, create a new commit to complete the merge:
git commit -m "the conflict in example.txt is merged and resolved"
|git status||Helps find out conflicted files.|
|git log --merge||Creates a log with a list of commits having conflict between the merging branches.|
|git diff||Finds differences between the states of a repository or files. Executing git diff can predict and prevent merge conflicts.|
|Tools to resolve failure on start|
|git checkout||Undoes changes to the files and changes branches.|
|git reset --mixed||Undoes changes to the working directory and staging area.|
|Tools to resolve failure during merge|
|git merge --abort||Exits from the merge process and returns the branch to the state before it began.|
|git reset||Resets conflicted files to a known good state.|