Next: , Previous: Revision Numbers, Up: A Day With CVS


Detecting And Resolving Conflicts

Detecting a conflict is easy enough. When you run update, CVS tells you, in no uncertain terms, that there's a conflict. But first, let's create the conflict. We edit hello.c to insert the line

     printf ("this change will conflict\n");

right where qsmith committed this:

     printf ("between hello and goodbye\n");

At this point, the status of our copy of hello.c is

     floss$ cvs status hello.c
     ===================================================================
     File: hello.c           Status: Needs Merge
     
        Working revision:    1.2     Mon Apr 19 02:17:07 1999
        Repository revision: 1.3     /usr/local/cvs/myproj/hello.c,v
        Sticky Tag:          (none)
        Sticky Date:         (none)
        Sticky Options:      (none)
     
     floss$

meaning that there are changes both in the repository and the working copy, and these changes need to be merged. (CVS isn't aware that the changes will conflict, because we haven't run update yet.) When we do the update, we see this:

     floss$ cvs update hello.c
     RCS file: /usr/local/cvs/myproj/hello.c,v
     retrieving revision 1.2
     retrieving revision 1.3
     Merging differences between 1.2 and 1.3 into hello.c
     rcsmerge: warning: conflicts during merge
     cvs update: conflicts found in hello.c
     C hello.c
     floss$

The last line of output is the giveaway. The C in the left margin next to the filename indicates that changes have been merged, but that they conflict. The contents of hello.c now shows both changes:

     #include <stdio.h>
     
     void
     main ()
     {
       printf ("Hello, world!\n");
     <<<<<<< hello.c
       printf ("this change will conflict\n");
     =======
       printf ("between hello and goodbye\n");
     >>>>>>> 1.3
       printf ("Goodbye, world!\n");
     }

Conflicts are always shown delimited by conflict markers, in the following format:

     <<<<<<< (filename)
       the uncommitted changes in the working copy
       blah blah blah
     =======
       the new changes that came from the repository
       blah blah blah
       and so on
     >>>>>>> (latest revision number in the repository)

The Entries file also shows that the file is in a halfway state at the moment:

     floss$ cat CVS/Entries
     /README.txt/1.1.1.1/Sun Apr 18 18:18:22 1999//
     D/a-subdir////
     D/b-subdir////
     /hello.c/1.3/Result of merge+Tue Apr 20 03:59:09 1999//
     floss$

The way to resolve the conflict is to edit the file so that it contains whatever text is appropriate, removing the conflict markers in the process, and then to commit. This doesn't necessarily mean choosing one change over another; you could decide neither change is sufficient and rewrite the conflicting section (or indeed the whole file) completely. In this case, we'll adjust in favor of the first change, but with capitalization and punctuation slightly different from qsmith's:

     floss$ emacs hello.c
       (make the edits...)
     floss$ cat hello.c
     #include <stdio.h>
     
     void
     main ()
     {
       printf ("Hello, world!\n");
       printf ("BETWEEN HELLO AND GOODBYE.\n");
       printf ("Goodbye, world!\n");
     }
     floss$ cvs ci -m "adjusted middle line"
     cvs commit: Examining .
     cvs commit: Examining a-subdir
     cvs commit: Examining a-subdir/subsubdir
     cvs commit: Examining b-subdir
     Checking in hello.c;
     /usr/local/cvs/myproj/hello.c,v  <-  hello.c
     new revision: 1.4; previous revision: 1.3
     done
     floss$
Karl Fogel wrote this book. Buy a printed copy via his homepage at red-bean.com

copyright  ©  March 20 2019 sean dreilinger url: https://durak.org/sean/pubs/software/cvsbook/Detecting-And-Resolving-Conflicts.html