| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
When more than one person works on a software project
things often get complicated. Often, two people try to
edit the same file simultaneously. One solution, known
as file locking or reserved checkouts, is
to allow only one person to edit each file at a time.
This is the only solution with some version control
systems, including RCS and SCCS. Currently
the usual way to get reserved checkouts with CVS
is the cvs admin -l command (see section A.6.1 admin options). This is not as nicely integrated into
CVS as the watch features, described below, but it
seems that most people with a need for reserved
checkouts find it adequate.
It also may be possible to use the watches
features described below, together with suitable
procedures (not enforced by software), to avoid having
two people edit at the same time.
The default model with CVS is known as unreserved checkouts. In this model, developers can edit their own working copy of a file simultaneously. The first person that commits his changes has no automatic way of knowing that another has started to edit it. Others will get an error message when they try to commit the file. They must then use CVS commands to bring their working copy up to date with the repository revision. This process is almost automatic.
CVS also supports mechanisms which facilitate various kinds of communication, without actually enforcing rules like reserved checkouts do.
The rest of this chapter describes how these various models work, and some of the issues involved in choosing between them.
10.1 File status A file can be in several states 10.2 Bringing a file up to date 10.3 Conflicts example An informative example 10.4 Informing others about commits To cooperate you must inform 10.5 Several developers simultaneously attempting to run CVS Simultaneous repository access 10.6 Mechanisms to track who is editing files 10.7 Choosing between reserved or unreserved checkouts Reserved or unreserved checkouts?
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Based on what operations you have performed on a
checked out file, and what operations others have
performed to that file in the repository, one can
classify a file in a number of states. The states, as
reported by the status command, are:
add, and not yet
committed your changes.
remove, and not yet
committed your changes.
update rather than
checkout to get that newer revision.
update command gave a conflict. If you have not
already done so, you need to
resolve the conflict as described in 10.3 Conflicts example.
add.
To help clarify the file status, status also
reports the Working revision which is the
revision that the file in the working directory derives
from, and the Repository revision which is the
latest revision in the repository for the branch in
use.
The options to status are listed in
B. Quick reference to CVS commands. For information on its Sticky tag
and Sticky date output, see 4.9 Sticky tags.
For information on its Sticky options output,
see the `-k' option in A.16.1 update options.
You can think of the status and update
commands as somewhat complementary. You use
update to bring your files up to date, and you
can use status to give you some idea of what an
update would do (of course, the state of the
repository might change before you actually run
update). In fact, if you want a command to
display file status in a more brief format than is
displayed by the status command, you can invoke
$ cvs -n -q update |
The `-n' option means to not actually do the
update, but merely to display statuses; the `-q'
option avoids printing the name of each directory. For
more information on the update command, and
these options, see B. Quick reference to CVS commands.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
When you want to update or merge a file, use the update
command. For files that are not up to date this is roughly equivalent
to a checkout command: the newest revision of the file is
extracted from the repository and put in your working directory.
Your modifications to a file are never lost when you
use update. If no newer revision exists,
running update has no effect. If you have
edited the file, and a newer revision is available,
CVS will merge all changes into your working copy.
For instance, imagine that you checked out revision 1.4 and started
editing it. In the meantime someone else committed revision 1.5, and
shortly after that revision 1.6. If you run update on the file
now, CVS will incorporate all changes between revision 1.4 and 1.6 into
your file.
If any of the changes between 1.4 and 1.6 were made too
close to any of the changes you have made, an
overlap occurs. In such cases a warning is
printed, and the resulting file includes both
versions of the lines that overlap, delimited by
special markers.
See section A.16 update--Bring work tree in sync with repository, for a complete description of the
update command.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Suppose revision 1.4 of `driver.c' contains this:
#include <stdio.h>
void main()
{
parse();
if (nerr == 0)
gencode();
else
fprintf(stderr, "No code generated.\n");
exit(nerr == 0 ? 0 : 1);
}
|
Revision 1.6 of `driver.c' contains this:
#include <stdio.h>
int main(int argc,
char **argv)
{
parse();
if (argc != 1)
{
fprintf(stderr, "tc: No args expected.\n");
exit(1);
}
if (nerr == 0)
gencode();
else
fprintf(stderr, "No code generated.\n");
exit(!!nerr);
}
|
Your working copy of `driver.c', based on revision 1.4, contains this before you run `cvs update':
#include <stdlib.h>
#include <stdio.h>
void main()
{
init_scanner();
parse();
if (nerr == 0)
gencode();
else
fprintf(stderr, "No code generated.\n");
exit(nerr == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
|
You run `cvs update':
$ cvs update driver.c RCS file: /usr/local/cvsroot/yoyodyne/tc/driver.c,v retrieving revision 1.4 retrieving revision 1.6 Merging differences between 1.4 and 1.6 into driver.c rcsmerge warning: overlaps during merge cvs update: conflicts found in driver.c C driver.c |
CVS tells you that there were some conflicts. Your original working file is saved unmodified in `.#driver.c.1.4'. The new version of `driver.c' contains this:
#include <stdlib.h>
#include <stdio.h>
int main(int argc,
char **argv)
{
init_scanner();
parse();
if (argc != 1)
{
fprintf(stderr, "tc: No args expected.\n");
exit(1);
}
if (nerr == 0)
gencode();
else
fprintf(stderr, "No code generated.\n");
<<<<<<< driver.c
exit(nerr == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
=======
exit(!!nerr);
>>>>>>> 1.6
}
|
Note how all non-overlapping modifications are incorporated in your working copy, and that the overlapping section is clearly markeresolve the conflict as described in 10.3 Conflicts example.
add.
To help clarify the file status, status also
reports the Working revision which is the
revision that the file in the working directory derives
from, and the Repository revision which is the
latest revision in the repository for the branch in
use.
The options to status are listed in
B. Quick reference to CVS commands. For information on its Sticky tag
and Sticky date output, see 4.9 Sticky tags.
For information on its Sticky options output,
see the `-k' option in A.16.1 update options.
You can think of the status and update
commands as somewhat complementary. You use
update to bring your files up to date, and you
can use status to give you some idea of what an
update would do (of course, the state of the
repository might change before you actually run
update). In fact, if you want a command to
display file status in a more brief format than is
displayed by the status command, you can invoke
$ cvs -n -q update |
The `-n' option means to not actually do the
update, but merely to display statuses; the `-q'
option avoids printing the name of each directory. For
more information on the update command, and
these options, see B. Quick reference to CVS commands.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
When you want to update or merge a file, use the update
command. For files that are not up to date this is roughly equivalent
to a checkout command: the newest revision of the file is
extracted from the repository and put in your working directory.
Your modifications to a file are never lost when you
use update. If no newer revision exists,
running update has no effect. If you have
edited the file, and a newer revision is available,
CVS will merge all changes into your working copy.
For instance, imagine that you checked out revision 1.4 and started
editing it. In the meantime someone else committed revision 1.5, and
shortly after that revision 1.6. If you run update on the file
now, CVS will incorporate all changes between revision 1.4 and 1.6 into
your file.
If any of the changes between 1.4 and 1.6 were made too
close to any of the changes you have made, an
overlap occurs. In such cases a warning is
printed, and the resulting file includes both
versions of the lines that overlap, delimited by
special markers.
See section A.16 update--Bring work tree in sync with repository, for a complete description of the
update command.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Suppose revision 1.4 of `driver.c' contains this:
#include <stdio.h>
void main()
{
parse();
if (nerr == 0)
gencode();
else
fprintf(stderr, "No code generated.\n");
exit(nerr == 0 ? 0 : 1);
}
|
Revision 1.6 of `driver.c' contains this:
#include <stdio.h>
int main(int argc,
char **argv)
{
parse();
if (argc != 1)
{
fprintf(stderr, "tc: No args expected.\n");
exit(1);
}
if (nerr == 0)
gencode();
else
fprintf(stderr, "No code generated.\n");
exit(!!nerr);
}
|
Your working copy of `driver.c', based on revision 1.4, contains this before you run `cvs update':
#include <stdlib.h>
#include <stdio.h>
void main()
{
init_scanner();
parse();
if (nerr == 0)
gencode();
else
fprintf(stderr, "No code generated.\n");
exit(nerr == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
|
You run `cvs update':
$ cvs update driver.c RCS file: /usr/local/cvsroot/yoyodyne/tc/driver.c,v retrieving revision 1.4 retrieving revision 1.6 Merging differences between 1.4 and 1.6 into driver.c rcsmerge warning: overlaps during merge cvs update: conflicts found in driver.c C driver.c |
CVS tells you that there were some conflicts. Your original working file is saved unmodified in `.#driver.c.1.4'. The new version of `driver.c' contains this:
#include <stdlib.h>
#include <stdio.h>
int main(int argc,
char **argv)
{
init_scanner();
parse();
if (argc != 1)
{
fprintf(stderr, "tc: No args expected.\n");
exit(1);
}
if (nerr == 0)
gencode();
else
fprintf(stderr, "No code generated.\n");
<<<<<<< driver.c
exit(nerr == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
=======
exit(!!nerr);
>>>>>>> 1.6
}
|
Note how all non-overlapping modifications are incorporated in your working copy, and that the overlapping section is clearly markeresolve the conflict as described in 10.3 Conflicts example.
add.
To help clarify the file status, status also
reports the Working revision which is the
revision that the file in the working directory derives
from, and the Repository revision which is the
latest revision in the repository for the branch in
use.
The options to status are listed in
B. Quick reference to CVS commands. For information on its Sticky tag
and Sticky date output, see 4.9 Sticky tags.
For information on its Sticky options output,
see the `-k' option in A.16.1 update options.
You can think of the status and update
commands as somewhat complementary. You use
update to bring your files up to date, and you
can use status to give you some idea of what an
update would do (of course, the state of the
repository might change before you actually run
update). In fact, if you want a command to
display file status in a more brief format than is
displayed by the status command, you can invoke
$ cvs -n -q update |
The `-n' option means to not actually do the
update, but merely to display statuses; the `-q'
option avoids printing the name of each directory. For
more information on the update command, and
these options, see B. Quick reference to CVS commands.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
When you want to update or merge a file, use the update
command. For files that are not up to date this is roughly equivalent
to a checkout command: the newest revision of the file is
extracted from the repository and put in your working directory.
Your modifications to a file are never lost when you
use update. If no newer revision exists,
running update has no effect. If you have
edited the file, and a newer revision is available,
CVS will merge all changes into your working copy.
For instance, imagine that you checked out revision 1.4 and started
editing it. In the meantime someone else committed revision 1.5, and
shortly after that revision 1.6. If you run update on the file
now, CVS will incorporate all changes between revision 1.4 and 1.6 into
your file.
If any of the changes between 1.4 and 1.6 were made too
close to any of the changes you have made, an
overlap occurs. In such cases a warning is
printed, and the resulting file includes both
versions of the lines that overlap, delimited by
special markers.
See section A.16 update--Bring work tree in sync with repository, for a complete description of the
update command.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Suppose revision 1.4 of `driver.c' contains this:
#include <stdio.h>
void main()
{
parse();
if (nerr == 0)
gencode();
else
fprintf(stderr, "No code generated.\n");
exit(nerr == 0 ? 0 : 1);
}
|
Revision 1.6 of `driver.c' contains this:
#include <stdio.h>
int main(int argc,
char **argv)
{
parse();
if (argc != 1)
{
fprintf(stderr, "tc: No args expected.\n");
exit(1);
}
if (nerr == 0)
gencode();
else
fprintf(stderr, "No code generated.\n");
exit(!!nerr);
}
|
Your working copy of `driver.c', based on revision 1.4, contains this before you run `cvs update':
#include <stdlib.h>
#include <stdio.h>
void main()
{
init_scanner();
parse();
if (nerr == 0)
gencode();
else
fprintf(stderr, "No code generated.\n");
exit(nerr == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
|
You run `cvs update':
$ cvs update driver.c RCS file: /usr/local/cvsroot/yoyodyne/tc/driver.c,v retrieving revision 1.4 retrieving revision 1.6 Merging differences between 1.4 and 1.6 into driver.c rcsmerge warning: overlaps during merge cvs update: conflicts found in driver.c C driver.c |
CVS tells you that there were some conflicts. Your original working file is saved unmodified in `.#driver.c.1.4'. The new version of `driver.c' contains this:
#include <stdlib.h>
#include <stdio.h>
int main(int argc,
char **argv)
{
init_scanner();
parse();
if (argc != 1)
{
fprintf(stderr, "tc: No args expected.\n");
exit(1);
}
if (nerr == 0)
gencode();
else
fprintf(stderr, "No code generated.\n");
<<<<<<< driver.c
exit(nerr == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
=======
exit(!!nerr);
>>>>>>> 1.6
}
|
Note how all non-overlapping modifications are incorporated in your working copy, and that the overlapping section is clearly markeresolve the conflict as described in 10.3 Conflicts example.
add.
To help clarify the file status, status also
reports the Working revision which is the
revision that the file in the working directory derives
from, and the Repository revision which is the
latest revision in the repository for the branch in
use.
The options to status are listed in
B. Quick reference to CVS commands. For information on its Sticky tag
and Sticky date output, see 4.9 Sticky tags.
For information on its Sticky options output,
see the `-k' option in A.16.1 update options.
You can think of the status and update
commands as somewhat complementary. You use
update to bring your files up to date, and you
can use status to give you some idea of what an
update would do (of course, the state of the
repository might change before you actually run
update). In fact, if you want a command to
display file status in a more brief format than is
displayed by the status command, you can invoke
$ cvs -n -q update |
The `-n' option means to not actually do the
update, but merely to display statuses; the `-q'
option avoids printing the name of each directory. For
more information on the update command, and
these options, see B. Quick reference to CVS commands.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
When you want to update or merge a file, use the update
command. For files that are not up to date this is roughly equivalent
to a checkout command: the newest revision of the file is
extracted from the repository and put in your working directory.
Your modifications to a file are never lost when you
use update. If no newer revision exists,
running update has no effect. If you have
edited the file, and a newer revision is available,
CVS will merge all changes into your working copy.
For instance, imagine that you checked out revision 1.4 and started
editing it. In the meantime someone else committed revision 1.5, and
shortly after that revision 1.6. If you run update on the file
now, CVS will incorporate all changes between revision 1.4 and 1.6 into
your file.
If any of the changes between 1.4 and 1.6 were made too
close to any of the changes you have made, an
overlap occurs. In such cases a warning is
printed, and the resulting file includes both
versions of the lines that overlap, delimited by
special markers.
See section A.16 update--Bring work tree in sync with repository, for a complete description of the
update command.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Suppose revision 1.4 of `driver.c' contains this:
#include <stdio.h>
void main()
{
parse();
if (nerr == 0)
gencode();
else
fprintf(stderr, "No code generated.\n");
exit(nerr == 0 ? 0 : 1);
}
|
Revision 1.6 of `driver.c' contains this:
#include <stdio.h>
int main(int argc,
char **argv)
{
parse();
if (argc != 1)
{
fprintf(stderr, "tc: No args expected.\n");
exit(1);
}
if (nerr == 0)
gencode();
else
fprintf(stderr, "No code generated.\n");
exit(!!nerr);
}
|
Your working copy of `driver.c', based on revision 1.4, contains this before you run `cvs update':
#include <stdlib.h>
#include <stdio.h>
void main()
{
init_scanner();
parse();
if (nerr == 0)
gencode();
else
fprintf(stderr, "No code generated.\n");
exit(nerr == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
|
You run `cvs update':
$ cvs update driver.c RCS file: /usr/local/cvsroot/yoyodyne/tc/driver.c,v retrieving revision 1.4 retrieving revision 1.6 Merging differences between 1.4 and 1.6 into driver.c rcsmerge warning: overlaps during merge cvs update: conflicts found in driver.c C driver.c |
CVS tells you that there were some conflicts. Your original working file is saved unmodified in `.#driver.c.1.4'. The new version of `driver.c' contains this:
#include <stdlib.h>
#include <stdio.h>
int main(int argc,
char **argv)
{
init_scanner();
parse();
if (argc != 1)
{
fprintf(stderr, "tc: No args expected.\n");
exit(1);
}
if (nerr == 0)
gencode();
else
fprintf(stderr, "No code generated.\n");
<<<<<<< driver.c
exit(nerr == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
=======
exit(!!nerr);
>>>>>>> 1.6
}
|
Note how all non-overlapping modifications are incorporated in your working copy, and that the overlapping section is clearly markeresolve the conflict as described in 10.3 Conflicts example.
add.
To help clarify the file status, status also
reports the Working revision which is the
revision that the file in the working directory derives
from, and the Repository revision which is the
latest revision in the repository for the branch in
use.
The options to status are listed in
B. Quick reference to CVS commands. For information on its Sticky tag
and Sticky date output, see 4.9 Sticky tags.
For information on its Sticky options output,
see the `-k' option in A.16.1 update options.
You can think of the status and update
commands as somewhat complementary. You use
update to bring your files up to date, and you
can use status to give you some idea of what an
update would do (of course, the state of the
repository might change before you actually run
update). In fact, if you want a command to
display file status in a more brief format than is
displayed by the status command, you can invoke
$ cvs -n -q update |
The `-n' option means to not actually do the
update, but merely to display statuses; the `-q'
option avoids printing the name of each directory. For
more information on the update command, and
these options, see B. Quick reference to CVS commands.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
When you want to update or merge a file, use the update
command. For files that are not up to date this is roughly equivalent
to a checkout command: the newest revision of the file is
extracted from the repository and put in your working directory.
Your modifications to a file are never lost when you
use update. If no newer revision exists,
running update has no effect. If you have
edited the file, and a newer revision is available,
CVS will merge all changes into your working copy.
For instance, imagine that you checked out revision 1.4 and started
editing it. In the meantime someone else committed revision 1.5, and
shortly after that revision 1.6. If you run update on the file
now, CVS will incorporate all changes between revision 1.4 and 1.6 into
your file.
If any of the changes between 1.4 and 1.6 were made too
close to any of the changes you have made, an
overlap occurs. In such cases a warning is
printed, and the resulting file includes both
versions of the lines that overlap, delimited by
special markers.
See section A.16 update--Bring work tree in sync with repository, for a complete description of the
update command.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Suppose revision 1.4 of `driver.c' contains this:
#include <stdio.h>
void main()
{
parse();
if (nerr == 0)
gencode();
else
fprintf(stderr, "No code generated.\n");
exit(nerr == 0 ? 0 : 1);
}
|
Revision 1.6 of `driver.c' contains this:
#include <stdio.h>
int main(int argc,
char **argv)
{
parse();
if (argc != 1)
{
fprintf( |