4.5. Merging StrategiesChapter 3 contains a section on merging and resolving conflicts ("Updating the Sandbox Files from the Repository"). Conflicts are rare when the developers are working solely on the trunk and frequently committing to the same line of development. However, once a development team starts using branches, there is the potential for lines of development to be kept separate from each other for months at a time. This vastly increases the possibility for conflict, so I am expanding on the process of merging and resolving conflicts. Please read the section in Chapter 3 first, however, as this discussion is based upon knowledge of the information provided there. The process for a merge is as follows:
4.5.1. When Merging Is EasyThe easiest merges are the ones CVS can do by itself, with no human intervention. Those occur when a cvs update produces an M or P result against a file, and doesn't require any work from you. Those merges don't need any particular explanation, so this section is about the second-easiest merges. Merging is easy when you can simply include both sets of changes. Let's look at a case where the two changes are a comment on an existing function and the creation of a new function. In cases like this, where the changes don't affect each other, you can remove the conflict markers and any duplicate lines and recommit the file. Both Bob and Lisa check out revision 1.3. The relevant section of revision 1.3 looks like this: TotalTime+=temp-time; Add(event,temp-time); } time=temp; } Record[total++]=time; } Bob adds a comment at the end of the function. He commits, and his version now becomes revision 1.4. His section now looks like this: TotalTime+=temp-time; Add(event,temp-time); } time=temp; } Record[total++]=time; } /* Have we considered the null event? */ Lisa starts a new function on the same line. Her code looks like this: TotalTime+=temp-time; Add(event,temp-time); } time=temp; } Record[total++]=time; } long GetEvent( ) { She tries to commit, but gets the conflict warning. bash$ cvs commit cvs commit: Examining . cvs server: Up-to-date check failed for 'timed-events.c' cvs [server aborted]: correct above errors first! cvs commit: saving log message in /tmp/cvsgmS8tS So she runs update and crosses her fingers that she just gets an M or a P (merge or patch). But no, she gets a C, for conflict. bash$ cvs update cvs server: Updating . RCS file: /home/cvs/src/timed-events.c,v retrieving revision 1.3 retrieving revision 1.4 Merging differences between 1.3 and 1.4 into timed-events.c rcsmerge: warning: conflicts during merge cvs server: conflicts found in timed-events.c C timed-events.c She opens the file, and sees this: TotalTime+=temp-time; Add(event,temp-time); } time=temp; } <<<<<<< timed-events.c Record[total++]=time; } /* Have we considered the null event? */ ======= Record[total++]=time; } long GetEvent( ) { >>>>>>> 1.4 Oh well. It's not a major issue. She edits the file, removing the conflict markers, and commits. The new revision 1.5 is this: TotalTime+=temp-time; Add(event,temp-time); } time=temp; } Record[total++]=time; } /* Have we considered the null event? */ long GetEvent( ) { 4.5.2. When Merging Is DifficultHaving had it so easy, Bob and Lisa have become overconfident. They're not talking to each other enough, and they are both working on the same function. This often leads to problems. They check out revision 1.8, which looks like this: long GetEvent( ) { /* FIXME: Currently returns true regardless of events */ return TRUE; } Lisa commits first, and revision 1.9 has a change to the parameters of the function. long GetEvent(int* currentkey) { /* FIXME: Currently returns true regardless of events */ return TRUE; } Bob also changes the parameters (obviously, they both intend to change the content of the function as well): long GetEvent(char* name) { /* FIXME: Currently returns true regardless of events */ return TRUE; } Bob tries to commit and has the same problem Lisa did. He tries the update, just as she did, and gets a conflict marker. He opens the file and sees this: <<<<<<< timed-event.c long GetEvent(int* currentkey) ======= long GetEvent(char* name) >>>>>>> 1.9 { /* FIXME: Currently returns true regardless of events */ return TRUE; } He's not entirely sure who the other person editing the file is. He thinks it's Lisa, but just to be certain, he uses cvs annotate on the file. Annotations for timed-event.c *************** . . . 1.9 (lisa 13-Apr-2006): long GetEvent(int* currentkey) 1.5 (lisa 11-Apr-2006): { 1.5 (lisa 11-Apr-2006): /* FIXME: Currently returns true regardless of events */ . . . It is Lisa. He goes to her desk with the issue, and the pair of them discuss it. They agree on which parameters the function needs, and Bob then edits the file and commits. The function signature in revision 1.10 looks like this, and all is right in the world (until the next merge!): long GetEvent(int* currentkey, char* name) |