Merge Conflicts in GIT
If you use GIT as source control, you would most probably have run into merge conflicts.
Basically, this is Git’s way of saying the same file has been changed by two different sources and it does not know which version is correct.
GIT will flag the conflicts as follows using the following string of characters
<<<<<<< HEAD
=======
>>>>>>>
The developer will then have to review each of the conflicts and pick the lines of code that are appropriate ensuring that they are not overwriting any new code in the target.
So, what causes a merge conflict?
In short, it occurs when two developers simultaneously changing the same lines of code. So when the two changes are pushed to the target branch, GIT does not know which version to choose.
If you think in terms of commits, developer 1 will be missing developer 2’s changes and vice-versa from their branches, so when the developer who merges their changes second will be faced with conflicts as the second merge will be attempting to overwrite the code of the first. The issue is that the latter branch is missing the newer commits from the target.
Ideally your story branch/personal branch would contain all the commits from the remote branch you are trying to push your changes too. Often in medium to large-sized development teams, while you were working away on your changes, others may have pushed other changes/commits to the remote branch. So, by the time you are ready to push your changes to the remote branch, your branch will have fallen behind in terms of the number of commits. In most cases, these will not cause a merge conflict as it is not often two devs are changing the same portion of the same file at the same time but it is not unusual either.
The diagram below is visual display of this scenario.
Scenario
Developer 1 and Developer 2 both checkout a copy of the remote branch and locally modify the same line in the file above.
Developer 1 pushes their changes to the remote branch and is successful but when Developer 2 pushes their changes, they are faced with a merge conflict because they are attempting to change line 6, which was changed by Developer 1.
Ways to resolve conflicts
One way to avoid running into conflicts is by regularly syncing the local branch from the remote branch, e.g. just execute a pull from the remote branch into the local branch. Updating your branch regularly will update your branch with all the newer commits, making it less likely to run into conflicts.
Otherwise resolve the conflict as highlighted below
- Simple Environment Setup
If your team is fairly small and developers are working on a local copy of the remote branch, this approach to resolve merge conflicts will work.
Step 1
Pull from the remote branch. This brings the conflicting code to your local branch.
Step 2
Resolve the conflict manually. Commit locally.
Step 3
Push to the remote branch.
2. More Complex Setup
In a medium to large developer teams, it is usual to work with Pull Requests. Each developer works off their own branch or they may create a story branch for they work they are doing. These branches are then merged to a common development branch through pull-requests. This allows others to review the code being pushed into the common remote branch and allows for the code to go through an iteration of fixes and corrections before deemed suitable for merging and release.
In larger teams, it is more likely to come across merge conflicts as someone else working on a separate feature may change a file that is also being worked on by other devs. Depending on who is able to merge their changes first, the latter devs working in that same file may end up encountering merge issues.
The solution can be as highlighted above in the simple setup section, but rather than pushing the changes directly to the remote, the devs will be pushing their changes to their remote branch and creating a pull request to the common branch.
While this works, this may not be suitable for organisations where releases to the Live environment are managed on a per story basis. For instance, stories are picked individually depending on their status for releasing to the Production environment.
Consider the following scenario
Team Appy has 5 developers and they are each working on a story. The team schedules a release to the Production org every Thursday. The story sizes are all likely to be different, which means some may be ready before others and some can make it to the cut-off for the release while others will stay in development until future releases. In this case, whichever story is completed (code complete and test complete) by Thursday, will be automatically picked for the release.
In the above scenario, Dev 1 have completed their code changes and merged their changes to the common remote branch. Dev 1 made changes to a utilities class also shared by Dev 2. Dev 1’s story is now in testing but the testing effort is a lot bigger than the coding effort, so it looks like an unlikely candidate for the upcoming production release.
Dev 2 then proceeds to merge their changes to the shared common branch and is faced with a conflict in the utilities file. If Dev 2 now tries to resolve the conflict by pulling the shared common branch into their local branch, Dev 1’s changes will end up in this story branch.
If subsequently, Dev 2’s story passes QA, this story would be dependent on Dev 1’s story passing QA before it is eligible for the Thursday release because Dev 1’s story branch now contains code from Dev 1 and Dev 2.
How to avoid this?
The best thing to do here is to leave the story branches untouched.
Here is how Dev 2 should tackle the conflict resolution:
- Make a copy of the shared remote branch, let’s call it Dev2merge_fix.
- Check out the Dev2merge_fix branch.
- Pull the Dev 2 story branch into the Dev2merge_fix branch and that will recreate the conflict locally.
- Resolve the conflict manually and commit.
- Push the changes to the remote Dev2merge_fix branch.
- Create a Pull Request from Dev2merge_fix branch to the shared Remote branch.
This way (assuming the code doesn’t require any fixes) another Pull Request can be created from the story branch to the release/master branch for the live release.
If further code changes are necessary, then the developer should make the changes on the story branch and merge the changes to the shared remote branch.