Situational guide to Git for new engineers - merge conflict

Situation: You done a lot of work but need to merge some remote changes

This is a very common and often dreaded situation. Local changes are all working fine and tests pass but there are remote changes to some of the same files and you are worried things will break.

There are a number of steps to take in order to perform a merge regardless if there are conflicts or not so this post is a bit longer.

If you currently have all your changes committed for your work branch then you first need to pull remote changes from main branch where you plan to merge your changes into eventually.

Successful merge commands:

git checkout main
git pull
git checkout myWorkingBranch
git merge main

Unsuccessful merge commands:

git checkout main
git pull
git checkout myWorkingBranch
git merge main
git config merge.tool opendiff - (optional one off see below)
git mergetool
git commit -am "Resolved conflict with MassiveViewController.swift"

Lets go over these.

Step 1

Switch to main branch command:

git checkout main

What does command do

This will change your current working branch to main on your local machine.

Step 2

Get most recent remote changes command:

git pull

or

git fetch && git pull

What does command do

The above commands will download latest remote changes to your local version of main branch.

Now that you have latest remote changes you can now attempt to merge them into your branch. This is fairly safe to do so don’t be afraid to try as changes are reservable and if there is a conflict and your conflict resolution has not played out well you can undo and try again.

Step 3

Switch back to your working branch command:

git checkout myWorkingBranch

What does command do

Now that you have the latest main branch from remote you can return to your branch you are working on and want to update. The next step is the merge.

Step 4

Switch back to your working branch command:

git checkout myWorkingBranch

What does command do

Now that you have the latest main branch from remote you can return to your branch you are working on and want to update. The next step is the merge.

Step 5 - Successful merge

Merge main into your branch command:

git merge main

What does command do

Merge changes from main into currently checked out branch. You should be on your working branch now which has become stale and needs some of the latest changes from main branch. Git will attempt to merge all changes from main branch into yours, if all is good it will perform what is known as fast forward merge.

If merge is successful it automatically commits the merge. So you do not need to make a manual commit.

Conflicts

In a well modularised codebase that follows good practices of keeping classes small this should be the most common situation as your work should not overlap with other developers on your team.

But when working on iOS projects that contain .xcodeproj files that often have conflicts based on insertion or deletion references of files in the project. These are not easily resolved by Git.

Or your codebase is currently in a bad state and you have to work with large classes that are being work on by multiple developers then you need to be careful.

Step 5 - Unsuccessful merge

Merge main into your branch command:

git merge main

What does command do

The same command will now return a console output to say there are number of merge conflicts and list some files. What to do next?

Output

$ git merge main
Auto-merging MassiveViewController.swift
CONFLICT (content): Merge conflict in MassiveViewController.swift
Automatic merge failed; fix conflicts and then commit the result.

At this point it’s time to bring in another tool. Without going too far I advise to start with OpenDiff. It is preinstalled on MacOS. It shows difference between local and remote changes and highlights conflicts in each file.

Step 6

Configure your conflict resolution tool command:

git config merge.tool opendiff

What does command do

Before it can be used you need to tell Git that OpenDiff will be used to resolve conflicts. You only need to run this command once as it will remember your choice. If you ever want to change your conflict resolution tool then you will run this command again with different editor.

Step 7

Open first file with conflict command:

git mergetool

What does command do

This command invokes a tool that is configured to show conflicts. Usually a side by side comparison of a file.

It opens one file at a time. Once you finished your changes, Use Save and then Quit. This will return to command line. If there are more than one file with conflicts it will open next file.

Example of OpenDiff Usage. This page provides a good example of how the tool looks and works.

Note

Once you resolved your differences and saved the changes to the file. Make sure to run the application and run tests inside Xcode. This will ensure that you have not make any accidental changes that break the application and your CI checks will not fail. It’s a good practice.

Step 8

Commit your merge command:

git commit -am "Resolved conflict with MassiveViewController.swift"

What does command do

This is a normal commit command discussed previously. Merge conflicts and resolutions are not automatically committed so you need to perform a manual commit.