Project25.View Three-Way Differences


Project 25. View Three-Way Differences

"I've got two sets of edits to the same file. How do I merge the changes so I can see both sets of changes in one file?"

This project shows how to compare two files against a common ancestor file and view their differences relative to the common file. It shows how to merge the two sets of changes to create a single file that contains both sets and how to make patch files that bring either of the two files up to date. The project covers commands diff3 and patch. It builds on concepts covered in Project 24, which uses commands diff, sdiff, and patch to compare and update pairs of files. Project 26 explores sorting of text files, and techniques for picking out commonalities and differences between sorted files.

Three-Way Comparison with diff3

We use the diff3 command to compare two files against a common ancestor file. If two people copy and then change the same file independently, diff3 can be used to merge both sets of changes into a new file. diff3 can also create a patch file describing the additional changes in one file compared with the other. When the patch is applied to the other file, the result is a file that contains both sets of changes.

The diff3 command reports on lines that have been added, deleted, and changed. It works on text or binary files, but we'll stick to text files in this project; it's simpler to illustrate the principles involved by using files that can be displayed.

The diff3 command is useful when two (or more) people make independent changes to their own copies of the same original file. We have two (or more) new files, both of which are relevant, so we must merge both sets of changes. At first glance, two people editing their own copies of the same file, at the same time, may seem a silly thing to do, but it is done often in software development. Many software engineers work on the same project in parallel, each engineer copying the same base set of files and applying his particular updates. Mostly, the engineers will change different files from one another, but occasionally, changes overlap. When development is complete, all sets of changes must be merged. This principle is employed by concurrent version control systems such as CVS, which uses diff3 to merge the changes as each developer returns his set of files to the base set.

Tip

For a list of the options understood by diff3, type

$ man diff3


For more information on diff3, type

$ info diff


(That's diff, not diff3.)


Let's look at an example that uses two independent sets of changes, made in files day1 and day2, to a common base file, orig. The three files are shown side by side. In day1, line 1 is edited, and line 5 is deleted. In day2, line 3 is edited, and line 7 is added. Our aim is to produce a merged file such that lines 1 and 3 are edited, line 5 is deleted, and line 7 is added, with respect to orig.

day1          orig          day2 line 11       line 1        line 1 line 2        line 2        line 2 line 3        line 3        line 33 line 4        line 4        line 4 line 6        line 5        line 5               line 6        line 6                             line 7


Tip

Specify one of the three files as a dash ( - ), and diff3 will read from its standard input instead of a file. This is usually combined with pipelining to compare the actual results of a command against preprescribed results held in a file.


We use diff3 to compare the changes made in day1 with those made in day2, relative to the base file orig.

You may be asking why the third file, orig, is required. It tells us that it was day1 that deleted line 5. Without comparing against orig, we couldn't be sure that it wasn't day2 that added line 5. Similarly, we know that day2 added line 7 and not that day1 deleted it. This information is important when the two files are merged, ensuring that diff knows to delete line 5 and add line 7 to produce the merged file.

Merge Two Sets of Changes

Having determined that day1 and day2 both contain changes to the original file, we now merge both sets of changes into day3. Recall that our aim is to produce a file such that lines 1 and 3 are edited, line 5 is deleted, and line 7 is added. To do this, simply specify option -m (merge) and redirect output to day3.

$ diff3 -m day1 orig day2 > day3 $ cat day3 line 11 line 2 line 33 line 4 line 6 line 7


Learn More

Refer to Project 6 to learn about redirection.


Patch the Differences

A more roundabout approach makes a patch file. First, use option -A and direct the output to the patch file.

$ diff3 -A day1 orig day2 > patchfile


Displaying patchfile, we see that it contains instructions on how to update day1 to incorporate the changes made to day2.

$ cat patchfile 5a line 7 . 3c line 33 .


Apply the patch to day1.

$ patch day1 patchfile $ cat day1 line 11 line 2 line 33 line 4 line 6 line 7


Tip

Be careful that patch is applied the correct way around. It does not warn you if it's applied the wrong way around.


Now day1 incorporates both sets of changes.

The patch could equally well be applied the other way around, as long as the diff is also done the other way around.

$ diff3 -A day2 orig day1 > patchfile $ patch day2 patchfile


Learn More

Project 24 shows you how to use patch with the command diff.


Resolve Conflicts

One final consideration: It's quite possible for the same line to be changed in both files, creating a conflict that must be resolved manually. (Computers are dumb.) This situation is illustrated below, where line 3 was changed in both files day1 and day2. You'll notice that diff produces a sequence of lines surrounded by <<<<<<< and >>>>>>> highlighting the area of conflict.

$ diff3 -m day1 orig day2 line 11 line 2 <<<<<<< day1 line 333 ||||||| orig line 3 ======= line 33 >>>>>>> day2 line 4 line 6 line 7


Whenever you merge two files, check for conflicts. You can check the return status of diff3 by examining the special shell variable $?. It's 0 for success and 1 for conflicts, and 2 means trouble (as the man page puts it).

$ diff3 -m day1 orig day2 > day3 $ echo $? 1


Learn More

Project 23 shows you how to use grep and wc.


Alternatively, dry-run the merge and count the number of conflicts.

$ diff3 -m day1 orig day2 | grep "<<<<" | wc -l       1


If you get conflicts, complete the merge and then edit the new file manually, choosing the appropriate line and removing the conflict markers.




Mac OS X UNIX 101 Byte-Sized Projects
Mac OS X Unix 101 Byte-Sized Projects
ISBN: 0321374118
EAN: 2147483647
Year: 2003
Pages: 153
Authors: Adrian Mayo

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net