Table of Contents
Introduction
I created a small PHP demo project to create and resolve a git merge conflict with the help of KDiff3. In this project I’ve created an index file that creates a house with a number of doors and windows. To get a better grasp of Git, you can read this post first. If you need to setup an access key for a remote repository like Bitbucket, additionally read all about that here.
Setup
On my PC I have a directory named test with two folders: A and B. These represent or simulate the same project that might have been on separate computers. Both A and B are a local git repository which point to the same remote repository. To be extra clear: Local Project A and B are local git repositories of the same project, which will only sync with the help of the same remote repository. A and B never communicate directly with each other.
Project changes, preparing the conflict
To create a merge conflict, I will edit the Door.php file in local version A, of which the content is as follows:
<?php
# Original version, synced over repository A, B and remote
namespace Test;
class Door {
protected $num;
public function __construct($num) {
$this->num = $num;
}
public function __toString() {
return "Door $this->num";
}
}
?>
PHPIn version A of the repository, I altered this file to the following:
<?php
# Edited version in repository A
namespace Test;
class Door {
protected $num;
public function __construct($num) {
$this->num = $num;
}
public function __toString() {
$str = "I am door number %d ";
return sprintf($str, $this->num);
}
}
?>
PHPIn version B of the repository, I altered this file to the following:
<?php
# Edited version in repository B
namespace Test;
class Door {
protected $number;
public function __construct($number) {
$this->number = $number;
}
public function __toString() {
return "Door $this->number";
}
}
?>
PHPThe merge conflict emerged
I have opened two Git bash terminals, one with project version A and one with project version B. Besides that, I have also opened to project two times in different instances of Visual Studio Code. Furthermore, I recommend using the Peacock plugin to distinguish between the different projects with the help of adjusting the color of one of the VSCode instances.
Meanwhile, as you maybe noticed in the code blocks above, line 14 is edited in both versions which will give the conflict.
Committing the changes
# project version A: www/test/A
git add .
git commit -m "Edited Door to make use of a formatted string"
git pull origin main # nothing will be pulled, as there are no changes
git push origin main
Bash# project version B: www/test/B
git add .
git commit -m "Edited variable name to make it more readable"
git pull origin main # here the merge conflict will occur
BashFrom https://bitbucket.org/<username>/<repos> * branch main -> FETCH_HEAD bd18f21..b0ca1b9 main -> origin/main Auto-merging Door.php CONFLICT (content): Merge conflict in Door.php Automatic merge failed; fix conflicts and then commit the result.
The content of Door.php of version B of the project is now altered to the following by Git:
<?php
namespace Test;
class Door {
protected $number;
public function __construct($number) {
$this->num = $number;
}
public function __toString() {
<<<<<<< HEAD
return "Door $this->number";
=======
$str = "I am a house with %d doors and %d windows";
return sprintf($str, count($this->doors), count($this->windows));
>>>>>>> b0ca1b9e58365a94bb64ba558ef13a275d0467e6
}
}
?>
BashInterpreting KDiff3
To resolve the merge conflict, we are going to use KDiff3. You can read about setting up KDiff3 with Git here in the Chapter configurations which is a subchapter of chapter The Flow.
# startup our configured merge tool, we run this from project version B
git mergetool
BashThis will open up KDiff3 in our case.
Three of the four lines that were altered could be automatically merged, because they were on different lines altogether.
- (A) Base (left window): Is the common ancestor, both altered versions of Door.php derive from this commit.
- (B) Local (middle window): Is version B of Door.php. The perspective from where we ran git mergetool from the command line. In other terms, this usually is the only local repository of the project you would have.
- (C) Remote (right window): Is version A of Door.php. This could be the work of a co-worker or friend. Don’t confuse “C”, the label of the version made by KDiff3, with “A” our version of the project. They have nothing to do with each other.
In the Window below these three, the end result of the merge conflict is displayed. The letter (A, B or C) in front of the lines tells you from which version the content is coming.
Solving the merge conflict
From the array of buttons in the lint above the three windows, we should go to the next unresolved conflict. Because there is only one conflict, this should already be selected. Otherwise, you go through each conflict one by one. Use the buttons with arrows displayed on it, or click on go to current delta to select the conflict. In any case, the buttons A, B, and C in the same lint should light up for selection. This means you can choose either version for the end result of the merge for each conflict at a time.
With the conflict selected, we should determine which version we want to keep. In our case, the most logical solution would be to choose for C, the change from the remote repository.
With the merge conflict selected, we click on C.
You can close KDiff3 after selecting C and click on save and exit when prompted. The merge is now complete.
Debugging
As you might have noticed, the variable name $num to $number was inconsistently changed. The file after the merge looks like the following:
<?php
namespace Test;
class Door {
protected $number;
public function __construct($number) {
$this->number = $number;
}
public function __toString() {
$str = "I am door number %d ";
return sprintf($str, $this->num); // error
}
}
PHPWe have to manually update line 15 to:
return sprintf($str, $this->number);
PHPThe only thing left is to commit the merge and push it to the remote repository. This concludes a way to resolve a Git merge conflict with the help of KDiff3.