Situatie
The Linux diff3 command detects differences between three text files. This helps you identify versions, understand their differences, and merge the changes. diff3’s great for source code, scripts, or any plain text file.
Solutie
A diff is the result of running a differencing tool on a set of files. The resulting output contains a list of the differences inside each of the files. The differences are identified by line number, and which file the difference is in. As you’d probably expect, diff3 creates diffs from three files.
Software version control (SVC) packages such as Git do diffs as part and parcel of what they are, and they do it exceptionally well. If you’re using Git or another SVC for diffing files, you should keep on doing so. It’s not just developers who can make use of diffs. If you’ve got any text-based material with different drafts stored in different files, you’re likely to find diffs helpful.
The diff3 command makes the difficult problem of diffing three files manageable.
How diff3 Is Different
diff3 takes three filenames as parameters. By convention, they’re referred to as mine, older, and yours, but they can be named anything. The mine, older, and yours model assumes an older ancestor file and two modified derivatives.
Here’s a simple example.
This is my-file.txt.
first line
second line
edited third line
This is old-file.txt.
first line
second line
third line
This is your-file.txt.
first line
second line
changed third line
We can perform a three-way diff by listing the files in order on the command line.
diff3
my-file.txt
old-file.txt
your-file.txt
diff3 reports that each file has a different third line.
The diff3 Output Format
Differences are displayed in hunks. A hunk starts with ‘====’ and an optional number, indicating which file the differences are from. The number is the position of the file on the command line. No number means all three files differ.
Here’s an example. Files older.txt and yours.txt contain these lines.
Line 1
Line 2
Line 3
File mine.txt contains a modified first line.
My file Line 1
Line 2
Line 3
Here’s the diff3 command.
diff3
mine.txt
older.txt
yours.txt
The ‘====1’ delimiter means file 1, or mine.txt.
The ‘1:’ means file one. The ‘1c’ means line one requires changing if it is to match the same line in the older file. The line is displayed.
The corresponding lines from files two and three are shown. Because they contain the same text as one another, it is listed once, but identified twice. The stacked ‘2:1c’ and ‘3:1c’ indicate the line appears in both files, with the line shown below them.
Let’s make mine.txt and yours.txt the same, with this text.
Line 1 Line 2 Line 3
The older.txt file has a modified second line.
Line 1 Older file Line 2 Line 3
We haven’t changed the filenames, so we can run the same command once more.
diff3 mine.txt older.txt yours.txt
The ‘2’ at the end of the delimiter ‘====2’ shows the difference in this hunk is in file two. The corresponding line from file one and three is displayed, and the line with the differences from file two is displayed.
Let’s modify file two once more, and add a line that isn’t in the other files.
Line 1 Older file Line 2 Line 3 Line 4
We can use our same command.
diff3 mine.txt older.txt yours.txt
This time, we have two hunks. Both delimiters refer to differences in file two.
The first hunk means line two in files one and three needs to be changed to match the same line in file two. Or, line two in file two needs to be changed to match the other two files.
The second hunk introduces a new piece of information. The older.txt file has a fourth line. The ‘1:3a’ and ‘3:3a’ tell us that in files one and three, a new line has to be appended after line three, to match file two. The line is shown below them.
The other thing diff3 can display is sequences of lines containing differences.
Let’s make mine.txt and older.txt the same, with this content.
Line 1 Line 2 Line 3
We’ll change two lines in yours.txt
Line 1 Yours Line 2 Yours Line 3
We’ll run the same command.
diff3 mine.txt older.txt yours.txt
This time, the line indicators don’t use a single line number. They have two line numbers separated by a comma ‘,’ to represent a range of lines. For example, ‘1:2,3c’ tells us that in file 1, lines two to three have differences.
Merging With diff3
Instead of getting diff3 to list the differences, we can ask diff3 to merge the contents and differences from the files into one single file. What it’s actually doing is rolling the differences between file three and file two, into file number one.
If you’re lucky, your files will merge with no conflicts. Sometimes there are changes in the same place in the files, causing conflicts. Conflicts are highlighted so you can choose which sets of lines you wish to keep.
The output is written to the terminal window, but you can easily redirect this into a file, then edit the file to review it.
Here’s a simple case. Here’s the contents of mine.txt.
We're going to run diff3 against these files. Yipee!
This is what’s in older.txt.
We're going to run diff3 against these files.
The yours.txt file contains this.
We're going to run the diff3 command against these files.
We’ll use our familiar command to do a diff, then we’ll run it again with the -m (merge) option to perform the merge.
diff3 mine.txt older.txt yours.txt diff3 -m mine.txt older.txt yours.txt
This blends the differences between older.txt and yours.txt into mine.txt, creating a new fourth version. To capture this output, add a redirect to the command.
diff3 -m mine.txt older.txt yours.txt > fourth.txt
Sadly, it’s rare your merges are that smooth. Here’s a more complicated example. The same lines are changed in several files.
Here’s our new mine.txt
chaffinch swallow pigeon sparrow nuthatch
This is our new older.txt
chaffinch swallow pigeon dove nuthatch
Finally, our new yours.txt.
chaffinch cuckoo rook dove nuthatch woodpecker goldfinch
This is the results of a diff.
diff3 mine.txt older.txt yours.txt
There are changes in all three files, and extra lines in one file. We’ll do a merge and redirect the output to a new file.
diff3 -m mine.txt older.txt yours.txt > new-file.txt
Using your favorite editor, open the file.
gedit new-file.txt
The section between the two delimiters ‘<<<<<<<’ and ‘>>>>>>>’ is a conflict.
The conflicting lines from each file are shown in turn. The lines from file one are between ‘<<<<<<<’ and ‘|||||||’, the lines from file two are between ‘|||||||’ and ‘=======’, and the lines from file three are between ‘=======’ and ‘>>>>>>>.’
On a real-world file you’re likely to have several areas of conflict to review and edit, to make them contain the text from the section you want to keep.