Published on 2020-06-28
Categories:
tech
Tags:
Linux
coding
tools
git
100DaysToOffload
I’m creating this post after seeing many people suffering and manually addressing merge conflicts while integrating patches with dwm, st, or dmenu code base.
The most common issues seen:
In my previous git post, I went over how to create and apply patches to a git repository.
In this post, I’ll show how conflict can be solved using tools.
Note: I’m going to use git, but these techniques are not unique to git.
In this example, I’ll start by using meld diff tool. In a later section, I’ll also show different tools.
You first need to install meld.
It can be installed on Linux, windows, OS X. Most distribution package it, or head over to their website.
After it’s installed, we need to tell git to use this tool as a mergetool:
|
|
You can then inspect the your ~/.gitconfig and you should see a section like this:
|
|
To do some experiment, I’m creating a local git repository, with 1 file with some text:
|
|
We have a new repository with file1 containing text:
|
|
Lets inspect the history by running the command:
|
|
|
|
Now lets create a condition for a conflict that is trivial to merge.
We first create a branch and add a line:
|
|
|
|
And we can see what is in file1:
|
|
|
|
Now lets go back to master and add a change to the first line:
|
|
|
|
And we can see what is in file1:
|
|
|
|
As you can see, we have 2 commits with different changes to file1.
We only have a conflict if we want to integrate changes from one branch to another.
Lets do this by merging changes from our feature branch to master:
|
|
|
|
And we can see what is in file1:
|
|
|
|
As you can see trivial conflicts are automatically merged.
The history now looks like this:
|
|
|
|
What you can read from this history:
Now lets create a conflicts that you will have to merge manually.
We will make changes to line 3 from both our feature branch and our master branch:
|
|
|
|
The history now looks like this:
|
|
|
|
The commit at the top is on our new feature branch.
Now lets change line 3 on master:
|
|
|
|
The history now looks like this:
|
|
|
|
What happens if we merge our feature branch? We have a conflict that cannot be resolved automatically:
|
|
|
|
And we can see what is in file1:
|
|
|
|
In the file1, you can see changes from both branches.
You could at this point, open your text editor and manually resolve the conflict by keeping the text we want, and removing the conflict markers (««<, »»>, ===
).
This is what many people do on YouTube when applying patches and trying to resolve conflicts. What you may not realize, is we have tools to do this, like meld, vimdiff, kdiff3.
With our previous configuration, all we need is to run the command:
|
|
This screen should appear:
What can you get from this screen:
I will take both changes, save and close meld.
After all of this is done, you can commit the changes:
|
|
You’ll be prompted to keep or change the default commit message.
I’m going to accept the default message.
Voila! Now you know how to resolve conflicts using tools.
You can use the merge –abort option to abort an ongoing merge and then start again.
Similar tool than meld. GUI based.
You just need to configure your merge.tool git configuration to kdiff3.
Here is a screenshot of the same merge conflict above, but this time with kdiff3:
Kdiff3 adds a 4th pane, the editing pane.
The base is the common ancestor, the local and remote are like for meld, the changes to the current branch and the branch we want to merge.
Clicking on A/B/C allows you to select which change(s) you want to get. The bottom pane shows you these and also allows you to edit.
Vimdiff is similar to kdiff3 with the 4 panes, except it’s console base. You will find your way if your familiar with vim.
Just set the merge.tool git configuration to vimdiff.
Here is the merge conflict as seen with vimdiff:
Bindings:
Window numbers:
Again, the file window can be edited. This is vim, so you can use any vim commands.
In case where you have trivial and non-trivial conflicts, tools react differently:
The problem of resolving conflicts may not appear to be that big for an example like above, but over many files and many changes, it’s the best way to resolve them with consistency and quality.
What I’ve learned during this post? I still prefer kdiff3 over meld as a merge tool due to automatic trivial conflict resolution of kdiff3. I haven’t tried Emacs ediff too, will come when I try replacing IntelliJ with emacs lsp-mode in the future.
In my next post, I’ll demo how I organize, apply and merge patches for st using: branches, git apply, and a merge tool.
I hope you learned something :)
This is day 9 of my #100DaysToOffload. You can read more about the challenge here: https://100daystooffload.com.
For comments, use email or Mastodon
Don't forget to subscribe to my RSS feed!