1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
|
This is Info file cvs.info, produced by Makeinfo-1.55 from the input
file ./cvs.texinfo.
Copyright (C) 1992, 1993 Signum Support AB Copyright (C) 1993, 1994
Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.
Permission is granted to copy and distribute modified versions of
this manual under the conditions for verbatim copying, provided also
that the section entitled "GNU General Public License" is included
exactly as in the original, and provided that the entire resulting
derived work is distributed under the terms of a permission notice
identical to this one.
Permission is granted to copy and distribute translations of this
manual into another language, under the above conditions for modified
versions, except that the section entitled "GNU General Public License"
and this permission notice may be included in translations approved by
the Free Software Foundation instead of in the original English.
File: cvs.info, Node: Updating a file, Next: Conflicts example, Prev: File status, Up: Multiple developers
Bringing a file up to date
==========================
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 copy of the module.
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. *Note update::,
for a complete description of the `update' command.
File: cvs.info, Node: Conflicts example, Next: Informing others, Prev: Updating a file, Up: Multiple developers
Conflicts example
=================
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 marked with
`<<<<<<<', `=======' and `>>>>>>>'.
You resolve the conflict by editing the file, removing the markers
and the erroneous line. Suppose you end up with this file:
#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");
exit(nerr == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
You can now go ahead and commit this as revision 1.7.
$ cvs commit -m "Initialize scanner. Use symbolic exit values." driver.c
Checking in driver.c;
/usr/local/cvsroot/yoyodyne/tc/driver.c,v <-- driver.c
new revision: 1.7; previous revision: 1.6
done
If you use release 1.04 or later of pcl-cvs (a GNU Emacs front-end
for CVS) you can use an Emacs package called emerge to help you resolve
conflicts. See the documentation for pcl-cvs.
File: cvs.info, Node: Informing others, Next: Concurrency, Prev: Conflicts example, Up: Multiple developers
Informing others about commits
==============================
It is often useful to inform others when you commit a new revision
of a file. The `-i' option of the `modules' file, or the `loginfo'
file, can be used to automate this process. *Note modules::. *Note
loginfo::. You can use these features of CVS to, for instance,
instruct CVS to mail a message to all developers, or post a message to
a local newsgroup.
File: cvs.info, Node: Concurrency, Next: Watches, Prev: Informing others, Up: Multiple developers
Several developers simultaneously attempting to run CVS
=======================================================
If several developers try to run CVS at the same time, one may get
the following message:
[11:43:23] waiting for bach's lock in /usr/local/cvsroot/foo
CVS will try again every 30 seconds, and either continue with the
operation or print the message again, if it still needs to wait. If a
lock seems to stick around for an undue amount of time, find the person
holding the lock and ask them about the cvs command they are running.
If they aren't running a cvs command, look for and remove files
starting with `#cvs.tfl', `#cvs.rfl', or `#cvs.wfl' from the repository.
Note that these locks are to protect CVS's internal data structures
and have no relationship to the word "lock" in the sense used by RCS-a
way to prevent other developers from working on a particular file.
Any number of people can be reading from a given repository at a
time; only when someone is writing do the locks prevent other people
from reading or writing.
One might hope for the following property
If someone commits some changes in one cvs command,
then an update by someone else will either get all the
changes, or none of them.
but CVS does *not* have this property. For example, given the files
a/one.c
a/two.c
b/three.c
b/four.c
if someone runs
cvs ci a/two.c b/three.c
and someone else runs `cvs update' at the same time, the person
running `update' might get only the change to `b/three.c' and not the
change to `a/two.c'.
File: cvs.info, Node: Watches, Prev: Concurrency, Up: Multiple developers
Mechanisms to track who is editing files
========================================
For many groups, use of CVS in its default mode is perfectly
satisfactory. Users may sometimes go to check in a modification only
to find that another modification has intervened, but they deal with it
and proceed with their check in. Other groups prefer to be able to
know who is editing what files, so that if two people try to edit the
same file they can choose to talk about who is doing what when rather
than be surprised at check in time. The features in this section allow
such coordination, while retaining the ability of two developers to
edit the same file at the same time.
For maximum benefit developers should use `cvs edit' (not `chmod')
to make files read-write to edit them, and `cvs release' (not `rm') to
discard a working directory which is no longer in use, but CVS is not
able to enforce this behavior.
* Menu:
* Setting a watch:: Telling CVS to watch certain files
* Getting Notified:: Telling CVS to notify you
* Editing files:: How to edit a file which is being watched
* Watch information:: Information about who is watching and editing
* Watches Compatibility:: Watches interact poorly with CVS 1.6 or earlier
File: cvs.info, Node: Setting a watch, Next: Getting Notified, Up: Watches
Telling CVS to watch certain files
----------------------------------
To enable the watch features, you first specify that certain files
are to be watched.
- Command: cvs watch on [`-l'] FILES ...
Specify that developers should run `cvs edit' before editing
FILES. CVS will create working copies of FILES read-only, to
remind developers to run the `cvs edit' command before working on
them.
If FILES includes the name of a directory, CVS arranges to watch
all files added to the corresponding repository directory, and
sets a default for files added in the future; this allows the user
to set notification policies on a per-directory basis. The
contents of the directory are processed recursively, unless the
`-l' option is given.
If FILES is omitted, it defaults to the current directory.
- Command: cvs watch off [`-l'] FILES ...
Do not provide notification about work on FILES. CVS will create
working copies of FILES read-write.
The FILES and `-l' arguments are processed as for `cvs watch on'.
File: cvs.info, Node: Getting Notified, Next: Editing files, Prev: Setting a watch, Up: Watches
Telling CVS to notify you
-------------------------
You can tell CVS that you want to receive notifications about
various actions taken on a file. You can do this without using `cvs
watch on' for the file, but generally you will want to use `cvs watch
on', so that developers use the `cvs edit' command.
- Command: cvs watch add [`-a' ACTION] [`-l'] FILES ...
Add the current user to the list of people to receive notification
of work done on FILES.
The `-a' option specifies what kinds of events CVS should notify
the user about. ACTION is one of the following:
`edit'
Another user has applied the `cvs edit' command (described
below) to a file.
`unedit'
Another user has applied the `cvs unedit' command (described
below) or the `cvs release' command to a file, or has deleted
the file and allowed `cvs update' to recreate it.
`commit'
Another user has committed changes to a file.
`all'
All of the above.
`none'
None of the above. (This is useful with `cvs edit',
described below.)
The `-a' option may appear more than once, or not at all. If
omitted, the action defaults to `all'.
The FILES and `-l' option are processed as for the `cvs watch'
commands.
- Command: cvs watch remove [`-a' ACTION] [`-l'] FILES ...
Remove a notification request established using `cvs watch add';
the arguments are the same. If the `-a' option is present, only
watches for the specified actions are removed.
When the conditions exist for notification, CVS calls the `notify'
administrative file, passing it the user to receive the notification
and the user who is taking the action which results in notification.
Normally `notify' will just send an email message.
Note that if you set this up in the straightforward way, users
receive notifications on the server machine. One could of course write
a `notify' script which directed notifications elsewhere, but to make
this easy, CVS allows you to associate a notification address for each
user. To do so create a file `users' in `CVSROOT' with a line for each
user in the format USER:VALUE. Then instead of passing the name of the
user to be notified to `notify', CVS will pass the VALUE (normally an
email address on some other machine).
File: cvs.info, Node: Editing files, Next: Watch information, Prev: Getting Notified, Up: Watches
How to edit a file which is being watched
-----------------------------------------
Since a file which is being watched is checked out read-only, you
cannot simply edit it. To make it read-write, and inform others that
you are planning to edit it, use the `cvs edit' command.
- Command: cvs edit [OPTIONS] FILES ...
Prepare to edit the working files FILES. CVS makes the FILES
read-write, and notifies users who have requested `edit'
notification for any of FILES.
The `cvs edit' command accepts the same OPTIONS as the `cvs watch
add' command, and establishes a temporary watch for the user on
FILES; CVS will remove the watch when FILES are `unedit'ed or
`commit'ted. If the user does not wish to receive notifications,
she should specify `-a none'.
The FILES and `-l' option are processed as for the `cvs watch'
commands.
Normally when you are done with a set of changes, you use the `cvs
commit' command, which checks in your changes and returns the watched
files to their usual read-only state. But if you instead decide to
abandon your changes, or not to make any changes, you can use the `cvs
unedit' command.
- Command: cvs unedit [`-l'] FILES ...
Abandon work on the working files FILES, and revert them to the
repository versions on which they are based. CVS makes those
FILES read-only for which users have requested notification using
`cvs watch on'. CVS notifies users who have requested `unedit'
notification for any of FILES.
The FILES and `-l' option are processed as for the `cvs watch'
commands.
When using client/server CVS, you can use the `cvs edit' and `cvs
unedit' commands even if CVS is unable to succesfully communicate with
the server; the notifications will be sent upon the next successful CVS
command.
File: cvs.info, Node: Watch information, Next: Watches Compatibility, Prev: Editing files, Up: Watches
Information about who is watching and editing
---------------------------------------------
- Command: cvs watchers [`-l'] FILES ...
List the users currently watching changes to FILES. The report
includes the files being watched, and the mail address of each
watcher.
The FILES and `-l' arguments are processed as for the `cvs watch'
commands.
- Command: cvs editors [`-l'] FILES ...
List the users currently working on FILES. The report includes
the mail address of each user, the time when the user began
working with the file, and the host and path of the working
directory containing the file.
The FILES and `-l' arguments are processed as for the `cvs watch'
commands.
File: cvs.info, Node: Watches Compatibility, Prev: Watch information, Up: Watches
Using watches with old versions of CVS
--------------------------------------
If you use the watch features on a repository, it creates `CVS'
directories in the repository and stores the information about watches
in that directory. If you attempt to use CVS 1.6 or earlier with the
repository, you get an error message such as
cvs update: cannot open CVS/Entries for reading: No such file or directory
and your operation will likely be aborted. To use the watch
features, you must upgrade all copies of CVS which use that repository
in local or server mode. If you cannot upgrade, use the `watch off' and
`watch remove' commands to remove all watches, and that will restore
the repository to a state which CVS 1.6 can cope with.
File: cvs.info, Node: Branches, Next: Merging, Prev: Multiple developers, Up: Top
Branches
********
So far, all revisions shown in this manual have been on the "main
trunk" of the revision tree, i.e., all revision numbers have been of
the form X.Y. One useful feature, especially when maintaining several
releases of a software product at once, is the ability to make branches
on the revision tree. "Tags", symbolic names for revisions, will also
be introduced in this chapter.
* Menu:
* Tags:: Tags-Symbolic revisions
* Branches motivation:: What branches are good for
* Creating a branch:: Creating a branch
* Sticky tags:: Sticky tags
File: cvs.info, Node: Tags, Next: Branches motivation, Up: Branches
Tags-Symbolic revisions
=======================
The revision numbers live a life of their own. They need not have
anything at all to do with the release numbers of your software
product. Depending on how you use CVS the revision numbers might
change several times between two releases. As an example, some of the
source files that make up RCS 5.6 have the following revision numbers:
ci.c 5.21
co.c 5.9
ident.c 5.3
rcs.c 5.12
rcsbase.h 5.11
rcsdiff.c 5.10
rcsedit.c 5.11
rcsfcmp.c 5.9
rcsgen.c 5.10
rcslex.c 5.11
rcsmap.c 5.2
rcsutil.c 5.10
You can use the `tag' command to give a symbolic name to a certain
revision of a file. You can use the `-v' flag to the `status' command
to see all tags that a file has, and which revision numbers they
represent.
The following example shows how you can add a tag to a file. The
commands must be issued inside your working copy of the module. That
is, you should issue the command in the directory where `backend.c'
resides.
$ cvs tag release-0-4 backend.c
T backend.c
$ cvs status -v backend.c
===================================================================
File: backend.c Status: Up-to-date
Version: 1.4 Tue Dec 1 14:39:01 1992
RCS Version: 1.4 /usr/local/cvsroot/yoyodyne/tc/backend.c,v
Sticky Tag: (none)
Sticky Date: (none)
Sticky Options: (none)
Existing Tags:
release-0-4 (revision: 1.4)
There is seldom reason to tag a file in isolation. A more common
use is to tag all the files that constitute a module with the same tag
at strategic points in the development life-cycle, such as when a
release is made.
$ cvs tag release-1-0 .
cvs tag: Tagging .
T Makefile
T backend.c
T driver.c
T frontend.c
T parser.c
(When you give CVS a directory as argument, it generally applies the
operation to all the files in that directory, and (recursively), to any
subdirectories that it may contain. *Note Recursive behavior::.)
The `checkout' command has a flag, `-r', that lets you check out a
certain revision of a module. This flag makes it easy to retrieve the
sources that make up release 1.0 of the module `tc' at any time in the
future:
$ cvs checkout -r release-1-0 tc
This is useful, for instance, if someone claims that there is a bug in
that release, but you cannot find the bug in the current working copy.
You can also check out a module as it was at any given date. *Note
checkout options::.
When you tag more than one file with the same tag you can think
about the tag as "a curve drawn through a matrix of filename vs.
revision number." Say we have 5 files with the following revisions:
file1 file2 file3 file4 file5
1.1 1.1 1.1 1.1 /--1.1* <-*- TAG
1.2*- 1.2 1.2 -1.2*-
1.3 \- 1.3*- 1.3 / 1.3
1.4 \ 1.4 / 1.4
\-1.5*- 1.5
1.6
At some time in the past, the `*' versions were tagged. You can
think of the tag as a handle attached to the curve drawn through the
tagged revisions. When you pull on the handle, you get all the tagged
revisions. Another way to look at it is that you "sight" through a set
of revisions that is "flat" along the tagged revisions, like this:
file1 file2 file3 file4 file5
1.1
1.2
1.1 1.3 _
1.1 1.2 1.4 1.1 /
1.2*----1.3*----1.5*----1.2*----1.1 (--- <--- Look here
1.3 1.6 1.3 \_
1.4 1.4
1.5
File: cvs.info, Node: Branches motivation, Next: Creating a branch, Prev: Tags, Up: Branches
What branches are good for
==========================
Suppose that release 1.0 of tc has been made. You are continuing to
develop tc, planning to create release 1.1 in a couple of months.
After a while your customers start to complain about a fatal bug. You
check out release 1.0 (*note Tags::.) and find the bug (which turns out
to have a trivial fix). However, the current revision of the sources
are in a state of flux and are not expected to be stable for at least
another month. There is no way to make a bugfix release based on the
newest sources.
The thing to do in a situation like this is to create a "branch" on
the revision trees for all the files that make up release 1.0 of tc.
You can then make modifications to the branch without disturbing the
main trunk. When the modifications are finished you can select to
either incorporate them on the main trunk, or leave them on the branch.
File: cvs.info, Node: Creating a branch, Next: Sticky tags, Prev: Branches motivation, Up: Branches
Creating a branch
=================
The `rtag' command can be used to create a branch. The `rtag'
command is much like `tag', but it does not require that you have a
working copy of the module. *Note rtag::. (You can also use the `tag'
command; *note tag::.).
$ cvs rtag -b -r release-1-0 release-1-0-patches tc
The `-b' flag makes `rtag' create a branch (rather than just a
symbolic revision name). `-r release-1-0' says that this branch should
be rooted at the node (in the revision tree) that corresponds to the tag
`release-1-0'. Note that the numeric revision number that matches
`release-1-0' will probably be different from file to file. The name
of the new branch is `release-1-0-patches', and the module affected is
`tc'.
To fix the problem in release 1.0, you need a working copy of the
branch you just created.
$ cvs checkout -r release-1-0-patches tc
$ cvs status -v driver.c backend.c
===================================================================
File: driver.c Status: Up-to-date
Version: 1.7 Sat Dec 5 18:25:54 1992
RCS Version: 1.7 /usr/local/cvsroot/yoyodyne/tc/driver.c,v
Sticky Tag: release-1-0-patches (branch: 1.7.2)
Sticky Date: (none)
Sticky Options: (none)
Existing Tags:
release-1-0-patches (branch: 1.7.2)
release-1-0 (revision: 1.7)
===================================================================
File: backend.c Status: Up-to-date
Version: 1.4 Tue Dec 1 14:39:01 1992
RCS Version: 1.4 /usr/local/cvsroot/yoyodyne/tc/backend.c,v
Sticky Tag: release-1-0-patches (branch: 1.4.2)
Sticky Date: (none)
Sticky Options: (none)
Existing Tags:
release-1-0-patches (branch: 1.4.2)
release-1-0 (revision: 1.4)
release-0-4 (revision: 1.4)
As the output from the `status' command shows the branch number is
created by adding a digit at the tail of the revision number it is
based on. (If `release-1-0' corresponds to revision 1.4, the branch's
revision number will be 1.4.2. For obscure reasons CVS always gives
branches even numbers, starting at 2. *Note Revision numbers::).
File: cvs.info, Node: Sticky tags, Prev: Creating a branch, Up: Branches
Sticky tags
===========
The `-r release-1-0-patches' flag that was given to `checkout' is
"sticky", that is, it will apply to subsequent commands in this
directory. If you commit any modifications, they are committed on the
branch. You can later merge the modifications into the main trunk.
*Note Merging::.
$ vi driver.c # Fix the bugs
$ cvs commit -m "Fixed initialization bug" driver.c
Checking in driver.c;
/usr/local/cvsroot/yoyodyne/tc/driver.c,v <-- driver.c
new revision: 1.7.2.1; previous revision: 1.7
done
$ cvs status -v driver.c
===================================================================
File: driver.c Status: Up-to-date
Version: 1.7.2.1 Sat Dec 5 19:35:03 1992
RCS Version: 1.7.2.1 /usr/local/cvsroot/yoyodyne/tc/driver.c,v
Sticky Tag: release-1-0-patches (branch: 1.7.2)
Sticky Date: (none)
Sticky Options: (none)
Existing Tags:
release-1-0-patches (branch: 1.7.2)
release-1-0 (revision: 1.7)
The sticky tags will remain on your working files until you delete
them with `cvs update -A'. *Note update::.
Sticky tags are not just for branches. If you check out a certain
revision (such as 1.4) it will also become sticky. Subsequent `cvs
update' will not retrieve the latest revision until you reset the tag
with `cvs update -A'.
See the descriptions in Appendix A for more information about sticky
tags. Dates and some other options can also be sticky. Again, see
Appendix A for details.
File: cvs.info, Node: Merging, Next: Recursive behavior, Prev: Branches, Up: Top
Merging
*******
You can include the changes made between any two revisions into your
working copy, by "merging". You can then commit that revision, and
thus effectively copy the changes onto another branch.
* Menu:
* Merging a branch:: Merging an entire branch
* Merging more than once:: Merging from a branch several times
* Merging two revisions:: Merging differences between two revisions
File: cvs.info, Node: Merging a branch, Next: Merging more than once, Up: Merging
Merging an entire branch
========================
You can merge changes made on a branch into your working copy by
giving the `-j BRANCH' flag to the `update' command. With one `-j
BRANCH' option it merges the changes made between the point where the
branch forked and newest revision on that branch (into your working
copy).
The `-j' stands for "join".
Consider this revision tree:
+-----+ +-----+ +-----+ +-----+
! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 ! <- The main trunk
+-----+ +-----+ +-----+ +-----+
!
!
! +---------+ +---------+
Branch R1fix -> +---! 1.2.2.1 !----! 1.2.2.2 !
+---------+ +---------+
The branch 1.2.2 has been given the tag (symbolic name) `R1fix'. The
following example assumes that the module `mod' contains only one file,
`m.c'.
$ cvs checkout mod # Retrieve the latest revision, 1.4
$ cvs update -j R1fix m.c # Merge all changes made on the branch,
# i.e. the changes between revision 1.2
# and 1.2.2.2, into your working copy
# of the file.
$ cvs commit -m "Included R1fix" # Create revision 1.5.
A conflict can result from a merge operation. If that happens, you
should resolve it before committing the new revision. *Note Conflicts
example::.
The `checkout' command also supports the `-j BRANCH' flag. The same
effect as above could be achieved with this:
$ cvs checkout -j R1fix mod
$ cvs commit -m "Included R1fix"
File: cvs.info, Node: Merging more than once, Next: Merging two revisions, Prev: Merging a branch, Up: Merging
Merging from a branch several times
===================================
Continuing our example, the revision tree now looks like this:
+-----+ +-----+ +-----+ +-----+ +-----+
! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !----! 1.5 ! <- The main trunk
+-----+ +-----+ +-----+ +-----+ +-----+
! *
! *
! +---------+ +---------+
Branch R1fix -> +---! 1.2.2.1 !----! 1.2.2.2 !
+---------+ +---------+
where the starred line represents the merge from the `R1fix' branch
to the main trunk, as just discussed.
Now suppose that development continues on the `R1fix' branch:
+-----+ +-----+ +-----+ +-----+ +-----+
! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !----! 1.5 ! <- The main trunk
+-----+ +-----+ +-----+ +-----+ +-----+
! *
! *
! +---------+ +---------+ +---------+
Branch R1fix -> +---! 1.2.2.1 !----! 1.2.2.2 !----! 1.2.2.3 !
+---------+ +---------+ +---------+
and then you want to merge those new changes onto the main trunk.
If you just use the `cvs update -j R1fix m.c' command again, CVS will
attempt to merge again the changes which you have already merged, which
can have undesirable side effects.
So instead you need to specify that you only want to merge the
changes on the branch which have not yet been merged into the trunk.
To do that you specify two `-j' options, and CVS merges the changes from
the first revision to the second revision. For example, in this case
the simplest way would be
cvs update -j 1.2.2.2 -j R1fix m.c # Merge changes from 1.2.2.2 to the
# head of the R1fix branch
The problem with this is that you need to specify the 1.2.2.2
revision manually. A slightly better approach might be to use the date
the last merge was done:
cvs update -j R1fix:yesterday -j R1fix m.c
Better yet, tag the R1fix branch after every merge into the trunk,
and then use that tag for subsequent merges:
cvs update -j merged_from_R1fix_to_trunk -j R1fix m.c
File: cvs.info, Node: Merging two revisions, Prev: Merging more than once, Up: Merging
Merging differences between any two revisions
=============================================
With two `-j REVISION' flags, the `update' (and `checkout') command
can merge the differences between any two revisions into your working
file.
$ cvs update -j 1.5 -j 1.3 backend.c
will *remove* all changes made between revision 1.3 and 1.5. Note the
order of the revisions!
If you try to use this option when operating on multiple files,
remember that the numeric revisions will probably be very different
between the various files that make up a module. You almost always use
symbolic tags rather than revision numbers when operating on multiple
files.
File: cvs.info, Node: Recursive behavior, Next: Adding files, Prev: Merging, Up: Top
Recursive behavior
******************
Almost all of the subcommands of CVS work recursively when you
specify a directory as an argument. For instance, consider this
directory structure:
`$HOME'
|
+--tc
| |
+--CVS
| (internal CVS files)
+--Makefile
+--backend.c
+--driver.c
+--frontend.c
+--parser.c
+--man
| |
| +--CVS
| | (internal CVS files)
| +--tc.1
|
+--testing
|
+--CVS
| (internal CVS files)
+--testpgm.t
+--test2.t
If `tc' is the current working directory, the following is true:
* `cvs update testing' is equivalent to `cvs update
testing/testpgm.t testing/test2.t'
* `cvs update testing man' updates all files in the subdirectories
* `cvs update .' or just `cvs update' updates all files in the `tc'
module
If no arguments are given to `update' it will update all files in
the current working directory and all its subdirectories. In other
words, `.' is a default argument to `update'. This is also true for
most of the CVS subcommands, not only the `update' command.
The recursive behavior of the CVS subcommands can be turned off with
the `-l' option.
$ cvs update -l # Don't update files in subdirectories
File: cvs.info, Node: Adding files, Next: Removing files, Prev: Recursive behavior, Up: Top
Adding files to a module
************************
To add a new file to a module, follow these steps.
* You must have a working copy of the module. *Note Getting the
source::.
* Create the new file inside your working copy of the module.
* Use `cvs add FILENAME' to tell CVS that you want to version
control the file.
* Use `cvs commit FILENAME' to actually check in the file into the
repository. Other developers cannot see the file until you
perform this step.
* If the file contains binary data it might be necessary to change
the default keyword substitution. *Note Keyword substitution::.
*Note admin examples::.
You can also use the `add' command to add a new directory inside a
module.
Unlike most other commands, the `add' command is not recursive. You
cannot even type `cvs add foo/bar'! Instead, you have to
$ cd foo
$ cvs add bar
*Note add::, for a more complete description of the `add' command.
File: cvs.info, Node: Removing files, Next: Tracking sources, Prev: Adding files, Up: Top
Removing files from a module
****************************
Modules change. New files are added, and old files disappear.
Still, you want to be able to retrieve an exact copy of old releases of
the module.
Here is what you can do to remove a file from a module, but remain
able to retrieve old revisions:
* Make sure that you have not made any uncommitted modifications to
the file. *Note Viewing differences::, for one way to do that.
You can also use the `status' or `update' command. If you remove
the file without committing your changes, you will of course not
be able to retrieve the file as it was immediately before you
deleted it.
* Remove the file from your working copy of the module. You can for
instance use `rm'.
* Use `cvs remove FILENAME' to tell CVS that you really want to
delete the file.
* Use `cvs commit FILENAME' to actually perform the removal of the
file from the repository.
What happens when you commit the removal of the file is that inside
the source repository, it is moved into a subdirectory called `Attic'.
cVS normally doesn't look in that directory when you run e.g.
`checkout'. However, if you are retrieving a certain revision via e.g.
`cvs checkout -r SOME-TAG', it will look at the files inside the
`Attic' and include any files that contain the specified tag.
File: cvs.info, Node: Tracking sources, Next: Moving files, Prev: Removing files, Up: Top
Tracking third-party sources
****************************
If you modify a program to better fit your site, you probably want
to include your modifications when the next release of the program
arrives. CVS can help you with this task.
In the terminology used in CVS, the supplier of the program is
called a "vendor". The unmodified distribution from the vendor is
checked in on its own branch, the "vendor branch". CVS reserves branch
1.1.1 for this use.
When you modify the source and commit it, your revision will end up
on the main trunk. When a new release is made by the vendor, you
commit it on the vendor branch and copy the modifications onto the main
trunk.
Use the `import' command to create and update the vendor branch.
After a successful `import' the vendor branch is made the `head'
revision, so anyone that checks out a copy of the file gets that
revision. When a local modification is committed it is placed on the
main trunk, and made the `head' revision.
* Menu:
* First import:: Importing a module for the first time
* Update imports:: Updating a module with the import command
File: cvs.info, Node: First import, Next: Update imports, Up: Tracking sources
Importing a module for the first time
=====================================
Use the `import' command to check in the sources for the first time.
When you use the `import' command to track third-party sources, the
"vendor tag" and "release tags" are useful. The "vendor tag" is a
symbolic name for the branch (which is always 1.1.1, unless you use the
`-b BRANCH' flag--*Note import options::). The "release tags" are
symbolic names for a particular release, such as `FSF_0_04'.
Suppose you use `wdiff' (a variant of `diff' that ignores changes
that only involve whitespace), and are going to make private
modifications that you want to be able to use even when new releases
are made in the future. You start by importing the source to your
repository:
$ tar xfz wdiff-0.04.tar.gz
$ cd wdiff-0.04
$ cvs import -m "Import of FSF v. 0.04" fsf/wdiff FSF WDIFF_0_04
The vendor tag is named `FSF' in the above example, and the only
release tag assigned is `WDIFF_0_04'.
File: cvs.info, Node: Update imports, Prev: First import, Up: Tracking sources
Updating a module with the import command
=========================================
When a new release of the source arrives, you import it into the
repository with the same `import' command that you used to set up the
repository in the first place. The only difference is that you specify
a different release tag this time.
$ tar xfz wdiff-0.05.tar.gz
$ cd wdiff-0.05
$ cvs import -m "Import of FSF v. 0.05" fsf/wdiff FSF WDIFF_0_05
For files that have not been modified locally, the newly created
revision becomes the head revision. If you have made local changes,
`import' will warn you that you must merge the changes into the main
trunk, and tell you to use `checkout -j' to do so.
$ cvs checkout -jFSF:yesterday -jFSF wdiff
The above command will check out the latest revision of `wdiff',
merging the changes made on the vendor branch `FSF' since yesterday
into the working copy. If any conflicts arise during the merge they
should be resolved in the normal way (*note Conflicts example::.).
Then, the modified files may be committed.
Using a date, as suggested above, assumes that you do not import
more than one release of a product per day. If you do, you can always
use something like this instead:
$ cvs checkout -jWDIFF_0_04 -jWDIFF_0_05 wdiff
In this case, the two above commands are equivalent.
File: cvs.info, Node: Moving files, Next: Moving directories, Prev: Tracking sources, Up: Top
Moving and renaming files
*************************
Moving files to a different directory or renaming them is not
difficult, but some of the ways in which this works may be non-obvious.
(Moving or renaming a directory is even harder. *Note Moving
directories::).
The examples below assume that the file OLD is renamed to NEW.
* Menu:
* Outside:: The normal way to Rename
* Inside:: A tricky, alternative way
* Rename by copying:: Another tricky, alternative way
File: cvs.info, Node: Outside, Next: Inside, Up: Moving files
The Normal way to Rename
========================
The normal way to move a file is to copy OLD to NEW, and then issue
the normal CVS commands to remove OLD from the repository, and add NEW
to it. (Both OLD and NEW could contain relative paths, for example
`foo/bar.c').
$ mv OLD NEW
$ cvs remove OLD
$ cvs add NEW
$ cvs commit -m "Renamed OLD to NEW" OLD NEW
This is the simplest way to move a file, it is not error-prone, and
it preserves the history of what was done. Note that to access the
history of the file you must specify the old or the new name, depending
on what portion of the history you are accessing. For example, `cvs
log OLD' will give the log up until the time of the rename.
When NEW is committed its revision numbers will start at 1.0 again,
so if that bothers you, use the `-r rev' option to commit (*note commit
options::.)
File: cvs.info, Node: Inside, Next: Rename by copying, Prev: Outside, Up: Moving files
Moving the history file
=======================
This method is more dangerous, since it involves moving files inside
the repository. Read this entire section before trying it out!
$ cd $CVSROOT/MODULE
$ mv OLD,v NEW,v
Advantages:
* The log of changes is maintained intact.
* The revision numbers are not affected.
Disadvantages:
* Old releases of the module cannot easily be fetched from the
repository. (The file will show up as NEW even in revisions from
the time before it was renamed).
* There is no log information of when the file was renamed.
* Nasty things might happen if someone accesses the history file
while you are moving it. Make sure no one else runs any of the CVS
commands while you move it.
File: cvs.info, Node: Rename by copying, Prev: Inside, Up: Moving files
Copying the history file
========================
This way also involves direct modifications to the repository. It
is safe, but not without drawbacks.
# Copy the RCS file inside the repository
$ cd $CVSROOT/MODULE
$ cp OLD,v NEW,v
# Remove the old file
$ cd ~/MODULE
$ rm OLD
$ cvs remove OLD
$ cvs commit OLD
# Remove all tags from NEW
$ cvs update NEW
$ cvs log NEW # Remember the tag names
$ cvs tag -d TAG1
$ cvs tag -d TAG2
...
By removing the tags you will be able to check out old revisions of
the module.
Advantages:
* Checking out old revisions works correctly, as long as you use
`-rTAG' and not `-DDATE' to retrieve the revisions.
* The log of changes is maintained intact.
* The revision numbers are not affected.
Disadvantages:
* You cannot easily see the history of the file across the rename.
* Unless you use the `-r rev' (*note commit options::.) flag when
NEW is committed its revision numbers will start at 1.0 again.
File: cvs.info, Node: Moving directories, Next: Keyword substitution, Prev: Moving files, Up: Top
Moving and renaming directories
*******************************
If you want to be able to retrieve old versions of the module, you
must move each file in the directory with the CVS commands. *Note
Outside::. The old, empty directory will remain inside the repository,
but it will not appear in your workspace when you check out the module
in the future.
If you really want to rename or delete a directory, you can do it
like this:
1. Inform everyone who has a copy of the module that the directory
will be renamed. They should commit all their changes, and remove
their working copies of the module, before you take the steps
below.
2. Rename the directory inside the repository.
$ cd $CVSROOT/MODULE
$ mv OLD-DIR NEW-DIR
3. Fix the CVS administrative files, if necessary (for instance if
you renamed an entire module).
4. Tell everyone that they can check out the module and continue
working.
If someone had a working copy of the module the CVS commands will
cease to work for him, until he removes the directory that disappeared
inside the repository.
It is almost always better to move the files in the directory
instead of moving the directory. If you move the directory you are
unlikely to be able to retrieve old releases correctly, since they
probably depend on the name of the directories.
File: cvs.info, Node: Keyword substitution, Next: Binary files, Prev: Moving directories, Up: Top
Keyword substitution
********************
As long as you edit source files inside your working copy of a
module you can always find out the state of your files via `cvs status'
and `cvs log'. But as soon as you export the files from your
development environment it becomes harder to identify which revisions
they are.
RCS uses a mechanism known as "keyword substitution" (or "keyword
expansion") to help identifying the files. Embedded strings of the form
`$KEYWORD$' and `$KEYWORD:...$' in a file are replaced with strings of
the form `$KEYWORD:VALUE$' whenever you obtain a new revision of the
file.
* Menu:
* Keyword list:: RCS Keywords
* Using keywords:: Using keywords
* Avoiding substitution:: Avoiding substitution
* Substitution modes:: Substitution modes
* Log keyword:: Problems with the $Log: cvs.info-2,v $
* Log keyword:: Problems with the Revision 1.1.1.2 1996/01/30 00:41:27 tholo
* Log keyword:: Problems with the Missed files from 1.7.1 import
* Log keyword:: Problems with the keyword.
File: cvs.info, Node: Keyword list, Next: Using keywords, Up: Keyword substitution
RCS Keywords
============
This is a list of the keywords that RCS currently (in release
5.6.0.1) supports:
`$Author: tholo $'
The login name of the user who checked in the revision.
`$Date: 1996/01/30 00:41:27 $'
The date and time (UTC) the revision was checked in.
`$Header: /cvs/OpenBSD/src/gnu/usr.bin/cvs/doc/cvs.info-2,v 1.1.1.2 1996/01/30 00:41:27 tholo Exp $'
A standard header containing the full pathname of the RCS file,
the revision number, the date (UTC), the author, the state, and
the locker (if locked). Files will normally never be locked when
you use CVS.
`$Id: cvs.info-2,v 1.1.1.2 1996/01/30 00:41:27 tholo Exp $'
Same as `$Header: /cvs/OpenBSD/src/gnu/usr.bin/cvs/doc/cvs.info-2,v 1.1.1.2 1996/01/30 00:41:27 tholo Exp $', except that the RCS filename is without a path.
`$Locker: $'
The login name of the user who locked the revision (empty if not
locked, and thus almost always useless when you are using CVS).
`$Log: cvs.info-2,v $
`Revision 1.1.1.2 1996/01/30 00:41:27 tholo
`Missed files from 1.7.1 import
`'
The log message supplied during commit, preceded by a header
containing the RCS filename, the revision number, the author, and
the date (UTC). Existing log messages are *not* replaced.
Instead, the new log message is inserted after `$Log: cvs.info-2,v $
Instead, the new log message is inserted after `Revision 1.1.1.2 1996/01/30 00:41:27 tholo
Instead, the new log message is inserted after `Missed files from 1.7.1 import
Instead, the new log message is inserted after `'. Each
new line is prefixed with a "comment leader" which RCS guesses
from the file name extension. It can be changed with `cvs admin
-c'. *Note admin options::. This keyword is useful for
accumulating a complete change log in a source file, but for
several reasons it can be problematic. *Note Log keyword::.
`$RCSfile: cvs.info-2,v $'
The name of the RCS file without a path.
`$Revision: 1.1.1.2 $'
The revision number assigned to the revision.
`$Source: /cvs/OpenBSD/src/gnu/usr.bin/cvs/doc/cvs.info-2,v $'
The full pathname of the RCS file.
`$State: Exp $'
The state assigned to the revision. States can be assigned with
`cvs admin -s'--*Note admin options::.
File: cvs.info, Node: Using keywords, Next: Avoiding substitution, Prev: Keyword list, Up: Keyword substitution
Using keywords
==============
To include a keyword string you simply include the relevant text
string, such as `$Id: cvs.info-2,v 1.1.1.2 1996/01/30 00:41:27 tholo Exp $', inside the file, and commit the file. CVS will
automatically expand the string as part of the commit operation.
It is common to embed `$Id: cvs.info-2,v 1.1.1.2 1996/01/30 00:41:27 tholo Exp $' string in the C source code. This
example shows the first few lines of a typical file, after keyword
substitution has been performed:
static char *rcsid="$Id: cvs.info-2,v 1.1.1.2 1996/01/30 00:41:27 tholo Exp $";
/* The following lines will prevent `gcc' version 2.X
from issuing an "unused variable" warning. */
#if __GNUC__ == 2
#define USE(var) static void * use_##var = (&use_##var, (void *) &var)
USE (rcsid);
#endif
Even though a clever optimizing compiler could remove the unused
variable `rcsid', most compilers tend to include the string in the
binary. Some compilers have a `#pragma' directive to include literal
text in the binary.
The `ident' command (which is part of the RCS package) can be used
to extract keywords and their values from a file. This can be handy
for text files, but it is even more useful for extracting keywords from
binary files.
$ ident samp.c
samp.c:
$Id: cvs.info-2,v 1.1.1.2 1996/01/30 00:41:27 tholo Exp $
$ gcc samp.c
$ ident a.out
a.out:
$Id: cvs.info-2,v 1.1.1.2 1996/01/30 00:41:27 tholo Exp $
SCCS is another popular revision control system. It has a command,
`what', which is very similar to `ident' and used for the same purpose.
Many sites without RCS have SCCS. Since `what' looks for the
character sequence `@(#)' it is easy to include keywords that are
detected by either command. Simply prefix the RCS keyword with the
magic SCCS phrase, like this:
static char *id="@(#) $Id: cvs.info-2,v 1.1.1.2 1996/01/30 00:41:27 tholo Exp $";
|