Training courses

Kernel and Embedded Linux

Bootlin training courses

Embedded Linux, kernel,
Yocto Project, Buildroot, real-time,
graphics, boot time, debugging...

Bootlin logo

Elixir Cross Referencer

   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
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
.\"	$NetBSD: rcs.ms,v 1.2 2016/01/14 04:22:39 christos Exp $
.\" pic file | tbl | troff -ms
.\"
.\" \*s stands for $, and avoids problems when this file is checked in.
.ds s $
.de D(
.DS
.nr VS 12p
.vs 12p
.I
..
.de D)
.DE
.nr VS 18p
.vs 18p
.R
..
.de Id
.ND \\$4
..
.Id Id: rcs.ms,v 5.4 1995/06/01 16:23:43 eggert Exp 
.RP
.TL
RCS\*-A System for Version Control
.sp
.AU
Walter F. Tichy
.AI
Department of Computer Sciences
Purdue University
West Lafayette, Indiana 47907
.sp
.AB
An important problem in program development and maintenance is version control,
i.e., the task of keeping a software system consisting of many versions and
configurations well organized.
The Revision Control System (RCS)
is a software tool that assists with that task.
RCS manages revisions of text documents, in particular source programs,
documentation, and test data.
It automates the storing, retrieval, logging and identification of revisions,
and it provides selection mechanisms for composing configurations.
This paper introduces basic version control concepts and
discusses the practice of version control
using RCS.
For conserving space, RCS stores deltas, i.e., differences between
successive revisions.  Several delta storage methods are discussed.
Usage statistics show that RCS's delta storage method is
space and time efficient.
The paper concludes with a detailed survey of version control tools.
.sp
\fBKeywords\fR: configuration management, history management,
version control, revisions, deltas.
.AE
.FS
An earlier version of this paper was published in
.I "Software\*-Practice & Experience"
.B 15 ,
7 (July 1985), 637-654.
.FE
.nr VS 18p
.LP
.NH
Introduction
.PP
Version control is the task of keeping software
systems consisting of many versions and configurations well organized.
The Revision Control System (RCS) is a set of UNIX
commands that assist with that task.
.PP
RCS' primary function is to manage \fIrevision groups\fR.
A revision group is a set of text documents, called \fIrevisions\fR,
that evolved from each other.  A new revision is
created by manually editing an existing one.
RCS organizes the revisions into an ancestral tree.  The initial revision
is the root of the tree, and the tree edges indicate
from which revision a given one evolved.
Besides managing individual revision groups, RCS provides
flexible selection functions for composing configurations.
RCS may be combined with MAKE\u1\d,
resulting in a powerful package for version control.
.PP
RCS also offers facilities for
merging updates with customer modifications,
for distributed software development, and
for automatic identification.
Identification is the `stamping'
of revisions and configurations with unique markers.
These markers are akin to serial numbers,
telling software maintainers unambiguously which configuration
is before them.
.PP
RCS is designed for both production and experimental
environments.
In production environments,
access controls detect update conflicts and prevent overlapping changes.
In experimental environments, where strong controls are
counterproductive, it is possible to loosen the controls.
.PP
Although RCS was originally intended for programs, it is useful for any
text that is revised frequently and whose previous revisions must be
preserved.  RCS has been applied successfully to store the source
text for drawings, VLSI layouts, documentation, specifications,
test data, form letters and articles.
.PP
This paper discusses the practice of
version control using RCS.
It also introduces basic version control concepts,
useful for clarifying current practice and designing similar systems.
Revision groups of individual components are treated in the next three sections,
and the extensions to configurations follow.
Because of its size, a survey of version control tools
appears at the end of the paper.
.NH
Getting started with RCS
.PP
Suppose a text file \fIf.c\fR is to be placed under control of RCS.
Invoking the check-in command
.D(
ci  f.c
.D)
creates a new revision group with the contents of
\fIf.c\fR as the initial
revision (numbered 1.1)
and stores the group into the file \fIf.c,v\fR.
Unless told otherwise, the command deletes \fIf.c\fR.
It also asks for a description of the group.
The description should state the common purpose of all revisions in the group,
and becomes part of the group's documentation.
All later check-in commands will ask for a log entry,
which should summarize the changes made.
(The first revision is assigned a default log message,
which just records the fact that it is the initial revision.)
.PP
Files ending in \fI,v\fR
are called \fIRCS files\fR (\fIv\fR stands for \fIv\fRersions);
the others are called working files.
To get back the working file \fIf.c\fR in the previous example,
execute the check-out command:
.D(
co  f.c
.D)
.R
This command extracts the latest revision from
the revision group \fIf.c,v\fR and writes
it into \fIf.c\fR.
The file \fIf.c\fR can now be edited and, when finished,
checked back in with \fIci\fR:
.D(
ci  f.c
.D)
\fICi\fR assigns number 1.2 to
the new revision.
If \fIci\fR complains with the message
.D(
ci error: no lock set by <login>
.D)
then the system administrator has decided to configure RCS for a
production environment by enabling the `strict locking feature'.
If this feature is enabled, all RCS files are initialized
such that check-in operations require a lock on the previous revision
(the one from which the current one evolved).
Locking prevents overlapping modifications if several people work on the same file.
If locking is required, the revision should
have been locked during the check-out by using
the option \fI\-l\fR:
.D(
co  \-l  f.c
.D)
Of course it is too late now for the check-out with locking, because
\fIf.c\fR has already been changed; checking out the file again
would overwrite the modifications.
(To prevent accidental overwrites, \fIco\fR senses the presence
of a working file and asks whether the user really intended to overwrite it.
The overwriting check-out is sometimes useful for
backing up to the previous revision.)
To be able to proceed with the check-in in the present case, first execute
.D(
rcs  \-l  f.c
.D)
This command retroactively locks the latest revision, unless someone
else locked it in the meantime.  In this case, the two programmers
involved have to negotiate whose
modifications should take precedence.
.PP
If an RCS file is private, i.e., if only the owner of the file is expected
to deposit revisions into it, the strict locking feature is unnecessary and
may be disabled.
If strict locking is disabled,
the owner of the RCS file need not have a lock for check-in.
For safety reasons, all others
still do.  Turning strict locking off and on is done with the commands:
.D(
rcs  \-U  f.c       \fRand\fP         rcs  \-L  f.c
.D)
These commands enable or disable the strict locking feature for each RCS file
individually.
The system administrator only decides whether strict locking is
enabled initially.
.PP
To reduce the clutter in a working directory, all RCS files can be moved
to a subdirectory with the name \fIRCS\fR.
RCS commands look first into that directory for RCS files.
All the commands presented above work
with the \fIRCS\fR subdirectory without change.\(dg
.FS \(dg
Pairs of RCS and working files can actually be specified in 3 ways:
a) both are given, b) only the working file is given, c) only the
RCS file is given.
If a pair is given, both files may have arbitrary path prefixes;
RCS commands pair them up intelligently.
.FE
.PP
It may be undesirable that \fIci\fR deletes the working file.
For instance, sometimes one would like to save the current revision,
but continue editing.
Invoking
.D(
ci  \-l  f.c
.D)
checks in \fIf.c\fR as usual, but performs an additional
check-out with locking afterwards.  Thus, the working file does
not disappear after the check-in.
Similarly, the option
\fI\-u\fR does a check-in followed by a check-out without
locking.  This option is useful if the file is needed for compilation after the check-in.
Both options update the identification markers in the working file
(see below).
.PP
Besides the operations \fIci\fR and \fIco\fR, RCS provides the following
commands:
.sp 0
.nr VS 12p
.vs 12p
.TS
tab(%);
li l.
ident%extract identification markers
rcs%change RCS file attributes
rcsclean%remove unchanged working files (optional)
rcsdiff%compare revisions
rcsfreeze%record a configuration (optional)
rcsmerge%merge revisions
rlog%read log messages and other information in RCS files
.TE
A synopsis of these commands appears in the Appendix.
.NH 2
Automatic Identification
.PP
RCS can stamp source and object code with special identification strings,
similar to product and serial numbers.
To obtain such identification, place the marker
.D(
\*sId\*s
.D)
into the text of a revision, for instance inside a comment.
The check-out operation will replace this marker with a string of the form
.D(
\*sId:  filename  revisionnumber  date  time  author  state  locker \*s
.D)
This string need never be touched, because \fIco\fR keeps it
up to date automatically.
To propagate the marker into object code, simply put
it into a literal character string.  In C, this is done as follows:
.D(
static char rcsid[] = \&"\*sId\*s\&";
.D)
The command \fIident\fR extracts such markers from any file, in particular from
object code.
\fIIdent\fR helps to find out
which revisions of which modules were used in a given program.
It returns a complete and unambiguous component list,
from which a copy of the program can be reconstructed.
This facility is invaluable for program maintenance.
.PP
There are several additional identification markers, one for each component
of \*sId\*s.
The marker
.D(
\*sLog\*s
.D)
has a similar function.  It accumulates
the log messages that are requested during check-in.
Thus, one can maintain the complete history of a revision directly inside it,
by enclosing it in a comment.
Figure 1 is an edited version of a log contained in revision 4.1 of
the file \fIci.c\fR.  The log appears at the beginning of the file,
and makes it easy to determine what the recent modifications were.
.sp
.nr VS 12p
.vs 12p
.ne 18
.nf
.in +0.5i
/*
.in +\w'/'u
* \*sLog: ci.c,v \*s
* Revision 4.1  1983/05/10 17:03:06  wft
* Added option \-d and \-w, and updated assignment of date, etc. to new delta.
* Added handling of default branches.
*
* Revision 3.9  1983/02/15 15:25:44  wft
* Added call to fastcopy() to copy remainder of RCS file.
*
* Revision 3.8  1983/01/14 15:34:05  wft
* Added ignoring of interrupts while new RCS file is renamed;
* avoids deletion of RCS files by interrupts.
*
* Revision 3.7  1982/12/10 16:09:20  wft
* Corrected checking of return code from diff.
* An RCS file now inherits its mode during the first ci from the working file,
* except that write permission is removed.
*/
.in 0
.ce 1
Figure 1.  Log entries produced by the marker \*sLog\*s.
.fi
.nr VS 18p
.vs 18p
.sp 0
.LP
Since revisions are stored in the form of differences,
each log message is
physically stored once,
independent of the number of revisions present.
Thus, the \*sLog\*s marker incurs negligible space overhead.
.NH
The RCS Revision Tree
.PP
RCS arranges revisions in an ancestral tree.
The \fIci\fR command builds this tree; the auxiliary command \fIrcs\fR
prunes it.
The tree has a root revision, normally numbered 1.1, and successive revisions
are numbered 1.2, 1.3, etc.  The first field of a revision number
is called the \fIrelease number\fR and the second one
the \fIlevel number\fR.  Unless given explicitly,
the \fIci\fR command assigns a new revision number
by incrementing the level number of the previous revision.
The release number must be incremented explicitly, using the
\fI\-r\fR option of \fIci\fR.
Assuming there are revisions 1.1, 1.2, and 1.3 in the RCS file f.c,v, the command
.D(
ci  \-r2.1  f.c       \fRor\fP       ci  \-r2  f.c
.D)
assigns the number 2.1 to the new revision.
Later check-ins without the \fI\-r\fR option will assign the numbers 2.2, 2.3,
and so on.
The release number should be incremented only at major transition points
in the development, for instance when a new release of a software product has
been completed.
.NH 2
When are branches needed?
.PP
A young revision tree is slender:
It consists of only one branch, called the trunk.
As the tree ages, side branches may form.
Branches are needed in the following 4 situations.
.IP "\fITemporary fixes\fR"
.sp 0
Suppose a tree has 5 revisions grouped in 2 releases,
as illustrated in Figure 2.
Revision 1.3, the last one of release 1, is in operation at customer sites,
while release 2 is in active development.
.ne 4
.PS 4i
.ps -2
box "1.1"
arrow
box "1.2"
arrow
box "1.3"
arrow
box "2.1"
arrow
box "2.2"
arrow dashed
.ps +2
.PE
.ce 1
Figure 2.  A slender revision tree.
.sp 0
Now imagine a customer requesting a fix of
a problem in revision 1.3, although actual development has moved on
to release 2.  RCS does not permit an extra
revision to be spliced in between 1.3 and 2.1, since that would not reflect
the actual development history.  Instead, create a branch
at revision 1.3, and check in the fix on that branch.
The first branch starting at 1.3 has number 1.3.1, and
the revisions on that branch are numbered 1.3.1.1, 1.3.1.2, etc.
The double numbering is needed to allow for another
branch at 1.3, say 1.3.2.
Revisions on the second branch would be numbered
1.3.2.1, 1.3.2.2, and so on.
The following steps create
branch 1.3.1 and add revision 1.3.1.1:
.sp 0
.I
.nr VS 12p
.vs 12p
.TS
tab(%);
l l l.
     %co  \-r1.3  f.c% \*- check out revision 1.3
     %edit  f.c% \*- change it
     %ci  \-r1.3.1  f.c% \*- check it in on branch 1.3.1
.TE
.nr VS 18p
.vs 18p
.R
This sequence of commands transforms the tree of Figure 2 into
the one in Figure 3.
Note that it may be necessary to incorporate the differences
between 1.3 and 1.3.1.1
into a revision at level 2.  The operation \fIrcsmerge\fR automates this
process (see the Appendix).
.ne 7
.PS 4i
.ps -2
     box "1.1"
     arrow
     box "1.2"
     arrow
R13: box "1.3"
     arrow
R21: box "2.1"
     arrow
R22: box "2.2"
     arrow dashed
     line invis down from R21.s
RB1: box "1.3.1.1"
     arrow dashed right from RB1.e
     arrow from R13.s to RB1.w
.ps +2
.PE
.ce 1
Figure 3.  A revision tree with one side branch
.sp
.IP "\fIDistributed development and customer modifications\fR"
.sp 0
Assume a situation as in Figure 2, where revision 1.3 is in operation
at several customer sites,
while release 2 is in development.
Customer sites should use RCS to store the distributed software.
However, customer modifications should not be placed on the same branch
as the distributed source; instead, they should be placed on a side branch.
When the next software distribution arrives,
it should be appended to the trunk of
the customer's RCS file, and the customer
can then merge the local modifications back into the new release.
In the above example, a
customer's RCS file would contain the following tree, assuming
that the customer has received revision 1.3, added his local modifications
as revision 1.3.1.1, then received revision 2.4, and merged
2.4 and 1.3.1.1, resulting in 2.4.1.1.
.ne 7
.PS 4i
.ps -2
R13: box "1.3"
     line invis
R21: box invis
     line invis
R22: box invis
     line invis
R24: box "2.4"
     line invis
R25: box invis
     line invis
     arrow from R13.e to R24.w
     line invis down from R21.s
RB1: box "1.3.1.1"
     arrow from R13.s to RB1.w
     right
     line invis down from R25.s
RB2: box "2.4.1.1"
     arrow from R24.s to RB2.w
.ps +2
.PE
.ce 1
Figure 4.  A customer's revision tree with local modifications.
.sp 1
This approach is actually practiced in the CSNET project,
where several universities and a company cooperate
in developing a national computer network.
.IP "\fIParallel development\fR"
.sp 0
Sometimes it is desirable to explore an alternate design or
a different implementation technique in parallel with the
main line development.  Such development
should be carried out on a side branch.
The experimental changes may later be moved into the main line, or abandoned.
.IP "\fIConflicting updates\fR"
.sp 0
A common occurrence is that one programmer
has checked out a revision, but cannot complete the assignment
for some reason.  In the meantime, another person
must perform another modification
immediately.  In that case, the second person should check-out the same revision,
modify it, and check it in on a side branch, for later merging.
.PP
Every node in a revision tree consists of the following attributes:
a revision number, a check-in date and time, the author's identification,
a log entry, a state and the actual text.  All these attributes
are determined at the time the revision is checked in.
The state attribute indicates the status of a revision.
It is set automatically to `experimental' during check-in.
A revision can later be promoted to a higher status, for example
`stable' or `released'.  The set of states is user-defined.
.NH 2
Revisions are represented as deltas
.PP
For conserving space, RCS stores revisions in the form
of deltas, i.e., as differences between revisions.
The user interface completely hides this fact.
.PP
A delta is a sequence of edit commands that transforms one string
into another.  The deltas employed by RCS are line-based, which means
that the only edit commands allowed are insertion and deletion of lines.
If a single character in a line is changed, the
edit scripts consider the entire line changed.
The program \fIdiff\fR\u2\d
produces a small, line-based delta between pairs of text files.
A character-based edit script would take much longer to compute,
and would not be significantly shorter.
.PP
Using deltas is a classical space-time tradeoff: deltas reduce the
space consumed, but increase access time.
However, a version control tool should impose as little delay
as possible on programmers.
Excessive delays discourage the use of version controls,
or induce programmers to take shortcuts that compromise system integrity.
To gain reasonably fast access time for both editing and compiling,
RCS arranges deltas in the following way.
The most recent revision on the trunk is stored intact.
All other revisions on the trunk are stored as reverse deltas.
A reverse delta describes how to go backward in the development history:
it produces the desired revision if applied to the successor of that revision.
This implementation has the advantage
that extraction of the latest revision is a simple and fast copy
operation.
Adding a new revision to the trunk is also fast: \fIci\fR simply
adds the new revision intact, replaces the previous
revision with a reverse delta, and keeps the rest of the old deltas.
Thus, \fIci\fR requires the computation
of only one new delta.
.PP
Branches need special treatment.  The naive solution would be to
store complete copies for the tips of all branches.
Clearly, this approach would cost too much space.  Instead,
RCS uses \fIforward\fR deltas for branches.  Regenerating a revision
on a side branch proceeds as follows.  First, extract the latest revision
on the trunk; secondly, apply reverse deltas until the fork revision for
the branch is obtained; thirdly, apply forward deltas until the desired
branch revision is reached.  Figure 5 illustrates a tree with
one side branch.  Triangles pointing to the left and right represent
reverse and forward deltas, respectively.
.ne 8
.PS 4i
.ps -2
define BD X [line invis $1 right .5;
line up .3 then left .5 down .3 then right .5 down .3 then up .3] X

define FD X [line invis $1 right .5;
line left .5 down .3 then up .6 then right .5 down .3;] X

right
D11:	BD(" 1.1")
	arrow right from D11.e
D12:	BD(" 1.2")
	arrow right from D12.e
D13:	BD(" 1.3")
	arrow right from D13.e
D21:	BD(" 2.1")
	arrow right from D21.e
D22:	box "2.2"
	line invis down from D21.s
F1:	FD("1.3.1.1 ")
	arrow from D13.se to F1.w
	arrow from F1.e right
	right
F2:	FD("1.3.1.2 ")
.ps +2
.PE
.ce 1
Figure 5.  A revision tree with reverse and forward deltas.
.sp 0
.PP
Although implementing fast check-out for the latest trunk revision,
this arrangement has the disadvantage that generation of other revisions
takes time proportional to the number of deltas applied.  For example,
regenerating the branch tip in Figure 5 requires application of five
deltas (including the initial one).  Since usage statistics show that
the latest trunk revision is the one that is retrieved in 95 per cent
of all cases (see the section on usage statistics), biasing check-out time
in favor of that revision results in significant savings.
However, careful implementation of the delta application process is
necessary to provide low retrieval overhead for other revisions, in
particular for branch tips.
.PP
There are several techniques for delta application.
The naive one is to pass each delta to a general-purpose text editor.
A prototype of RCS invoked the UNIX editor \fIed\fR both
for applying deltas and for expanding the identification markers.
Although easy to implement, performance was poor, owing to the
high start-up costs and excess generality of \fIed\fR.  An intermediate
version of RCS used a special-purpose, stream-oriented editor.
This technique reduced the cost of applying a delta to the cost of
checking out the latest trunk revision.  The reason for this behavior
is that each delta application involves a complete pass over
the preceding revision.
.PP
However, there is a much better algorithm.  Note that the deltas are
line oriented and that most of the work of a stream editor involves
copying unchanged lines from one revision to the next.  A faster
algorithm avoids unnecessary copying of character strings by using
a \fIpiece table\fR.
A piece table is a one-dimensional array, specifying how a given
revision is `pieced together' from lines in the RCS file.
Suppose piece table \fIPT\dr\u\fR represents revision \fIr\fR.
Then \fIPT\dr\u[i]\fR contains the starting position of line \fIi\fR
of revision \fIr\fR.
Application of the next delta transforms piece table \fIPT\dr\u\fR
into \fIPT\dr+1\u\fR.  For instance, a delete command removes a
series of entries from the piece table.  An insertion command inserts
new entries, moving the entries following the insertion point further down the
array.  The inserted entries point to the text lines in the delta.
Thus, no I/O is involved except for reading the delta itself.  When all
deltas have been applied to the piece table, a sequential pass
through the table looks up each line in the RCS file and copies it to
the output file, updating identification markers at the same time.
Of course, the RCS file must permit random access, since the copied
lines are scattered throughout that file.  Figure 6 illustrates an
RCS file with two revisions and the corresponding piece tables.
.ne 13
.sp 6
.ce 1
\fIFigure 6 is not available.\fP
.sp 5
.ce 1
Figure 6.  An RCS file and its piece tables
.sp 0
.PP
The piece table approach has the property that the time for applying a single
delta is roughly determined by the size of the delta, and not by the
size of the revision.  For example, if a delta is
10 per cent of the size of a revision, then applying it takes only
10 per cent of the time to generate the latest trunk revision.  (The stream
editor would take 100 per cent.)
.PP
There is an important alternative for representing deltas that affects
performance.  SCCS\u3\d,
a precursor of RCS, uses \fIinterleaved\fR deltas.
A file containing interleaved deltas is partitioned into blocks of lines.
Each block has a header that specifies to which revision(s) the block
belongs.  The blocks are sorted out in such a way that a single
pass over the file can pick up all the lines belonging to a given
revision.  Thus, the regeneration time for all revisions is the same:
all headers must be inspected, and the associated blocks either copied
or skipped.  As the number of revisions increases, the cost of retrieving
any revision is much higher than the cost of checking out the
latest trunk revision with reverse deltas.  A detailed comparison
of SCCS's interleaved deltas and RCS's reverse deltas can be found
in Reference 4.
This reference considers the version of RCS with the
stream editor only.  The piece table method improves performance
further, so that RCS is always faster than SCCS, except if 10
or more deltas are applied.
.PP
Additional speed-up for both delta methods can be obtained by caching
the most recently generated revision, as has been implemented in DSEE.\u5\d
With caching, access time to frequently used revisions can approach normal file
access time, at the cost of some additional space.
.NH
Locking: A Controversial Issue
.PP
The locking mechanism for RCS was difficult to design.
The problem and its solution are first presented in their `pure' form,
followed by a discussion of the complications
caused by `real-world' considerations.
.PP
RCS must prevent two or more persons from depositing competing changes of the
same revision.
Suppose two programmers check out revision 2.4 and
modify it.  Programmer A checks in a revision before programmer B\&.
Unfortunately, programmer B has not seen A's
changes, so the effect is that A's changes are covered up by B's deposit.
A's changes are not lost since all revisions
are saved, but they are confined to a single revision.\(dd
.FS \(dd
Note that this problem is entirely different from the atomicity problem.
Atomicity means that
concurrent update operations on the same RCS file cannot be permitted,
because that may result in inconsistent data.
Atomic updates are essential (and implemented in RCS),
but do not solve the conflict discussed here.
.FE
.PP
This conflict is prevented in RCS by locking.
Whenever someone intends to edit a revision (as opposed
to reading or compiling it), the revision should be checked out
and locked,
using the \fI\-l\fR option on \fIco\fR.  On subsequent check-in,
\fIci\fR tests the lock and then removes it.
At most one programmer at a time may
lock a particular revision, and only this programmer may check in
the succeeding revision.
Thus, while a revision is locked, it is the exclusive responsibility
of the locker.
.PP
An important maxim for software tools like RCS is that they must
not stand in the way of making progress with a project.
This consideration leads to several weakenings of the locking mechanism.
First of all, even if a revision is locked, it can
still be checked out.  This is necessary if other people
wish to compile or inspect the locked revision
while the next one is in preparation.  The only operations they
cannot do are to lock the revision or to check in the succeeding one.  Secondly,
check-in operations on other branches in the RCS file are still possible; the
locking of one revision does not affect any other revision.
Thirdly, revisions are occasionally locked for a long period of time
because a programmer is absent or otherwise unable to complete
the assignment.  If another programmer has to make a pressing change,
there are the following three alternatives for making progress:
a) find out who is holding the lock and ask that person to release it;
b) check out the locked revision, modify it, check it
in on a branch, and merge the changes later;
c) break the lock.  Breaking a lock leaves a highly visible
trace, namely an electronic mail message that is sent automatically to the
holder of the lock, recording the breaker and a commentary requested from him.
Thus, breaking locks is tolerated under certain circumstances,
but will not go unnoticed.
Experience has shown that the automatic mail message attaches a high enough
stigma to lock breaking,
such that programmers break locks only in real emergencies,
or when a co-worker resigns and leaves locked revisions behind.
.PP
If an RCS file is private, i.e., when a programmer owns an RCS file
and does not expect anyone else to perform check-in operations,
locking is an unnecessary nuisance.
In this case,
the `strict locking feature' discussed earlier may be disabled,
provided that file protection
is set such that only the owner may write the RCS file.
This has the effect that only the owner can check-in revisions,
and that no lock is needed for doing so.
.PP
As added protection,
each RCS file contains an access list that specifies the users
who may execute update operations.  If an access list is empty,
only normal UNIX file protection applies.  Thus, the access list is
useful for restricting the set of people who would otherwise have update
permission.  Just as with locking, the access list
has no effect on read-only operations such as \fIco\fR.  This approach
is consistent with the UNIX philosophy of openness, which contributes
to a productive software development environment.
.NH
Configuration Management
.PP
The preceding sections described how RCS deals with revisions of individual
components; this section discusses how to handle configurations.
A configuration is a set of revisions, where each revision comes
from a different revision group, and the revisions are selected
according to a certain criterion.
For example,
in order to build a functioning compiler, the `right'
revisions from the scanner, the parser, the optimizer
and the code generator must be combined.
RCS, in conjunction with MAKE,
provides a number of facilities to effect a smooth selection.
.NH 2
RCS Selection Functions
.PP
.IP "\fIDefault selection\fR"
.sp 0
During development, the usual selection criterion is to choose
the latest revision of all components.  The \fIco\fR command
makes this selection by default.  For example, the command
.D(
co  *,v
.D)
retrieves the latest revision on the default branch of each RCS file
in the current directory.
The default branch is usually the trunk, but may be
set to be a side branch.
Side branches as defaults are needed in distributed software development,
as discussed in the section on the RCS revision tree.
.sp
.IP "\fIRelease based selection\fR"
.sp 0
Specifying a release or branch number selects the latest revision in
that release or branch.
For instance,
.D(
co  \-r2  *,v
.D)
retrieves the latest revision with release number 2 from each RCS file.
This selection is convenient if a release has been completed and
development has moved on to the next release.
.sp
.IP "\fIState and author based selection\fR"
.sp 0
If the highest level number within a given release number
is not the desired one,
the state attribute can help.  For example,
.D(
co  \-r2  \-sReleased  *,v
.D)
retrieves the latest revision with release number 2 whose state attribute
is `Released'.
Of course, the state attribute has to be set appropriately, using the
\fIci\fR or \fIrcs\fR commands.
Another alternative is to select a revision by its author,
using the \fI\-w\fR option.
.sp
.IP "\fIDate based selection\fR"
.sp 0
Revisions may also be selected by date.
Suppose a release of an entire system was
completed and current on March 4, at 1:00 p.m. local time.  Then the command
.D(
co  \-d'March 4, 1:00 pm LT'  *,v
.D)
checks out all the components of that release, independent of the numbering.
The \fI\-d\fR option specifies a `cutoff date', i.e.,
the revision selected has a check-in date that
is closest to, but not after the date given.
.IP "\fIName based selection\fR"
.sp 0
The most powerful selection function is based on assigning symbolic
names to revisions and branches.
In large systems, a single release number or date is not sufficient
to collect the appropriate revisions from all groups.
For example, suppose one wishes to combine release 2
of one subsystem and release 15 of another.
Most likely, the creation dates of those releases differ also.
Thus, a single revision number or date passed to the \fIco\fR command
will not suffice to select the right revisions.
Symbolic revision numbers solve this problem.
Each RCS file may contain a set of symbolic names that are mapped
to numeric revision numbers.  For example, assume
the symbol \fIV3\fR is bound to release number 2 in file \fIs,v\fR, and to
revision number 15.9 in \fIt,v\fR.
Then the single command
.D(
co  \-rV3  s,v  t,v
.D)
retrieves the latest revision of release 2 from \fIs,v\fR,
and revision 15.9 from \fIt,v\fR.
In a large system with many modules, checking out all
revisions with one command greatly simplifies configuration management.
.PP
Judicious use of symbolic revision numbers helps with organizing
large configurations.
A special command, \fIrcsfreeze\fR,
assigns a symbolic revision number to a selected revision
in every RCS file.
\fIRcsfreeze\fR effectively freezes a configuration.
The assigned symbolic revision number selects all components
of the configuration.
If necessary, symbolic numbers
may even be intermixed with numeric ones.  Thus, \fIV3.5\fR in the
above example
would select revision 2.5 in \fIs,v\fR and branch 15.9.5 in \fIt,v\fR.
.PP
The options \fI\-r\fR, \fI\-s\fR, \fI\-w\fR and \fI\-d\fR
may be combined.  If a branch is given, the latest revision
on that branch satisfying all conditions is retrieved;
otherwise, the default branch is used.
.NH 2
Combining MAKE and RCS
.PP
MAKE\u1\d
is a program that processes configurations.
It is driven by configuration specifications
recorded in a special file, called a `Makefile'.
MAKE avoids redundant processing steps
by comparing creation dates of source and processed objects.
For example, when instructed to compile all
modules of a given system, it only recompiles
those source modules that were changed
since they were processed last.
.PP
MAKE has been extended with an auto-checkout feature for RCS.*
.FS *
This auto-checkout extension is available only in some versions of MAKE,
e.g. GNU MAKE.
.FE
When a certain file to be processed is not present,
MAKE attempts a check-out operation.
If successful, MAKE performs the required processing, and then deletes
the checked out file to conserve space.
The selection parameters discussed above can be passed to MAKE
either as parameters, or directly embedded in the Makefile.
MAKE has also been extended to search the subdirectory named \fIRCS\fR
for needed files, rather than just the current working directory.
However, if a working file is present, MAKE totally ignores the corresponding
RCS file and uses the working file.
(In newer versions of MAKE distributed by AT&T and others,
auto-checkout can be
achieved with the rule DEFAULT, instead of a special extension of MAKE.
However, a file checked out by the rule DEFAULT
will not be deleted after processing. \fIRcsclean\fR can be
used for that purpose.)
.PP
With auto-checkout, RCS/MAKE can effect a selection rule
especially tuned for multi-person software development and maintenance.
In these situations,
programmers should obtain configurations that consist of
the revisions they have personally checked out plus the latest
checked in revision of all other revision groups.
This schema can be set up as follows.
.PP
Each programmer chooses a working directory
and places into it a symbolic link, named \fIRCS\fR,
to the directory containing the relevant RCS files.
The symbolic link makes sure that \fIco\fR and \fIci\fR
operations need only specify the working files, and that
the Makefile need not be changed.
The programmer then checks out the needed files and modifies them.
If MAKE is invoked,
it composes configurations by selecting those
revisions that are checked out, and the rest from the
subdirectory \fIRCS\fR.
The latter selection may be controlled by a symbolic
revision number or any of the other selection criteria.
If there are several programmers editing in separate working directories,
they are insulated from each other's changes until checking in their
modifications.
.PP
Similarly, a maintainer can recreate an older configuration
by starting to work in an empty working directory.
During the initial MAKE invocation, all revisions are selected from RCS files.
As the maintainer checks out files and modifies them,
a new configuration is gradually built up.
Every time MAKE is invoked, it substitutes the modified revisions
into the configuration being manipulated.
.PP
A final application of RCS is to use it for storing Makefiles.
Revision groups of Makefiles represent
multiple versions of configurations.
Whenever a configuration is baselined or distributed,
the best approach is to unambiguously fix
the configuration with a symbolic revision number by calling
\fIrcsfreeze\fR,
to embed that symbol into the Makefile, and to
check in the Makefile (using the same symbolic revision number).
With this approach, old configurations
can be regenerated easily and reliably.
.NH
Usage Statistics
.PP
The following usage statistics were collected on two DEC VAX-11/780
computers of the Purdue Computer Science Department.  Both machines
are mainly used for research purposes.  Thus, the data
reflect an environment in which the majority of projects
involve prototyping and advanced software development,
but relatively little long-term maintenance.
.PP
For the first experiment,
the \fIci\fR and \fIco\fR operations were instrumented
to log the number of backward and forward deltas applied.
The data were collected during a 13 month period
from Dec. 1982 to Dec. 1983.
Table I summarizes the results.
.sp 0
.nr VS 12p
.vs 12p
.TS
center,box,tab(#);
c|c|c|c|c s|c s
c|c|c|c|c s|c s
l|n|n|n|n n|n n.
Operation#Total#Total deltas#Mean deltas#Operations#Branch
	 #operations #applied#applied#with >1 delta#operations
_
co     # 7867# 9320#1.18#509#(6%)#203#(3%)
ci     # 3468# 2207#0.64# 85#(2%)# 75#(2%)
ci & co#11335#11527#1.02#594#(5%)#278#(2%)
.TE
.ce 1
Table I.  Statistics for \fIco\fR and \fIci\fR operations.
.nr VS 18p
.vs 18p
.PP
The first two lines show statistics for check-out and check-in;
the third line shows the combination.
Recall that \fIci\fR performs an implicit check-out to obtain
a revision for computing the delta.
In all measures presented, the most recent revision (stored intact)
counts as one delta.  The number of deltas applied represents
the number of passes necessary, where the first `pass' is a copying step.
.PP
Note that the check-out operation is executed more than
twice as frequently as the check-in operation.
The fourth column gives the mean number of deltas
applied in all three cases.
For \fIci\fR, the mean number of deltas applied is less
than one.
The reasons are that the initial check-in requires no delta at all, and that
the only time \fIci\fR requires more than one delta is for branches.
Column 5 shows the actual number of operations that applied more than one
delta.
The last column indicates that branches were not used often.
.PP
The last three columns demonstrate that the most recent trunk revision
is by far the most frequently accessed.
For RCS, check-out of
this revision is a simple copy operation, which is the absolute minimum
given the copy-semantics of \fIco\fR.
Access to older revisions and branches
is more common in non-academic environments,
yet even if access to older deltas were an order
of magnitude more frequent,
the combined average number of deltas applied would still be below 1.2.
Since RCS is faster than SCCS until up to 10 delta applications,
reverse deltas are clearly the method of choice.
.PP
The second experiment, conducted in March of 1984,
involved surveying the existing RCS files
on our two machines.  The goal was to determine the mean number of
revisions per RCS file, as well as the space consumed by them.
Table II shows the results.  (Tables I and II were produced at different
times and are unrelated.)
.sp 0
.nr VS 12p
.vs 12p
.TS
center,box,tab(#);
c | c | c | c | c | c | c
c | c | c | c | c | c | c
l | n | n | n | n | n | n.
	  #Total RCS#Total#Mean#Mean size of#Mean size of#Overhead
	  #files#revisions#revisions#RCS files#revisions
_
All files #8033#11133#1.39#6156#5585#1.10
Files with#1477# 4578#3.10#8074#6041#1.34
\(>= 2 deltas
.TE
.ce 1
Table II.  Statistics for RCS files.
.nr VS 18p
.vs 18p
.PP
The mean number of revisions per RCS file is 1.39.
Columns 5 and 6 show the mean sizes (in bytes) of an RCS file
and of the latest revision of each RCS file, respectively.
The `overhead' column contains the ratio of the mean sizes.
Assuming that all revisions in an RCS file are approximately the same size,
this ratio gives a measure of the space consumed by the extra revisions.
.PP
In our sample, over 80 per cent of the RCS files contained only a single revision.
The reason is that our
systems programmers routinely check in all source files
on the distribution tapes, even though they may never touch them again.
To get a better indication of how much space savings are possible
with deltas, all measures with those files
that contained 2 or more revisions were recomputed.  Only for those files
is RCS necessary.
As shown in the second line, the average number of revisions for those files is
3.10, with an overhead of 1.34.  This means that the extra 2.10 deltas
require 34 per cent extra space, or
16 per cent per extra revision.
Rochkind\u3\d
measured the space consumed by SCCS, and
reported an average of 5 revisions per group
and an overhead of 1.37 (or about 9 per cent per extra revision).
In a later paper, Glasser\u6\d
observed an average of 7 revisions per group in a single, large project,
but provided no overhead figure.
In his paper on DSEE\u5\d,
Leblang reported that delta storage combined with blank compression
results in an overhead of a mere 1\-2 per cent per revision.
Since leading blanks accounted for about 20 per cent of the surveyed Pascal
programs, a revision group with 5\-10 members was smaller
than a single cleartext copy.
.PP
The above observations demonstrate clearly that the space needed
for extra revisions is small.  With delta storage, the luxury of
keeping multiple revisions online is certainly affordable.
In fact, introducing a system with delta storage may reduce
storage requirements, because programmers often save back-up copies
anyway.  Since back-up copies are stored much more efficiently with deltas,
introducing a system such as RCS may
actually free a considerable amount of space.
.NH
Survey of Version Control Tools
.PP
The need to keep back-up copies of software arose when
programs and data were no longer stored on paper media, but were entered
from terminals and stored on disk.
Back-up copies are desirable for reliability, and many modern editors
automatically save a back-up copy for every file touched.
This strategy
is valuable for short-term back-ups, but not suitable for long-term
version control, since an existing back-up copy is overwritten whenever the
corresponding file is edited.
.PP
Tape archives are suitable for long-term, offline storage.
If all changed files are dumped on a back-up tape once per day, old revisions
remain accessible.  However, tape archives are unsatisfactory
for version control in several ways.  First, backing up the file
system every 24 hours does not capture intermediate revisions.
Secondly, the old revisions are not online,
and accessing them is tedious and time-consuming.
In particular, it is impractical to
compare several old revisions of a group,
because that may require mounting and searching several tapes.
Tape archives are important fail-safe tools in the
event of catastrophic disk failures or accidental deletions,
but they are ill-suited for version control.
Conversely, version control tools do not obviate the
need for tape archives.
.PP
A natural technique for keeping several old revisions online is
to never delete a file.
Editing a file
simply creates a new file with the same
name, but with a different sequence number.
This technique, available as an option in DEC's VMS operating system,
turns out to be inadequate for version control.
First, it is prohibitively expensive in terms of storage costs,
especially since no data compression techniques are employed.
Secondly, indiscriminately storing every change produces too many
revisions, and programmers have difficulties distinguishing them.
The proliferation of revisions forces programmers to spend much time on
finding and deleting useless files.
Thirdly, most of the support functions like locking, logging,
revision selection,
and identification described in this paper are not available.
.PP
An alternative approach is to separate editing from revision control.
The user may repeatedly edit a given revision,
until freezing it with an explicit command.
Once a revision is frozen, it is stored permanently and can no longer be modified.
(In RCS, freezing a revisions is done with \fIci\fR.)
Editing a frozen revision implicitly creates a new one, which
can again be changed repeatedly until it is frozen itself.
This approach saves exactly those revisions that the user
considers important, and keeps the number of revisions manageable.
IBM's CLEAR/CASTER\u7\d,
AT&T's SCCS\u3\d,
CMU's SDC\u8\d
and DEC's CMS\u9\d,
are examples of version control systems using this approach.
CLEAR/CASTER maintains a data base of programs, specifications,
documentation and messages, using deltas.
Its goal is to provide control over the development process from a
management viewpoint.
SCCS stores multiple revisions of source text in an ancestral tree,
records a log entry for each revision,
provides access control, and has facilities
for uniquely identifying each revision.
An efficient delta technique
reduces the space consumed by each revision group.
SDC is much simpler than SCCS because it stores not more than
two revisions.  However, it maintains a complete log for all old
revisions, some of which may be on back-up tape.
CMS, like SCCS, manages tree-structured revision groups,
but offers no identification mechanism.
.PP
Tools for dealing with configurations are still in a state of flux.
SCCS, SDC and CMS can be combined with MAKE or MAKE-like programs.
Since flexible selection rules are missing from all these tools,
it is sometimes difficult
to specify precisely which revision of each group
should be passed to MAKE for building a desired configuration.
The Xerox Cedar system\u10\d
provides a `System Modeller' that can rebuild
a configuration from an arbitrary set of module revisions.
The revisions of a module are only distinguished by creation time,
and there is no tool for managing groups.
Since the selection rules are primitive,
the System Modeller appears to be somewhat tedious to use.
Apollo's DSEE\u5\d
is a sophisticated software engineering environment.
It manages revision groups in a way similar to SCCS and CMS.  Configurations
are built using `configuration threads'.
A configuration thread states which revision of each group
named in a configuration should be chosen.
A configuration thread may contain dynamic specifiers
(e.g., `choose the revisions I am currently working on,
and the most recent revisions otherwise'), which are bound
automatically at build time.
It also provides a notification mechanism for alerting
maintainers about the need to rebuild a system after a change.
.PP
RCS is based on a general model for describing
multi-version/multi-configuration systems\u11\d.
The model describes systems using AND/OR graphs, where AND nodes represent
configurations, and OR nodes represent version groups.
The model gives rise to a suit of selection rules for
composing configurations, almost all of which are implemented in RCS.
The revisions selected by RCS are passed to MAKE for configuration building.
Revision group management is modelled after SCCS.
RCS retains SCCS's best features,
but offers a significantly simpler user interface,
flexible selection rules, adequate integration with MAKE
and improved identification.
A detailed comparison of RCS and SCCS appears in Reference 4.
.PP
An important component of all revision control systems
is a program for computing deltas.
SCCS and RCS use the program \fIdiff\fR\u2\d,
which first computes the longest common substring of two
revisions, and then produces the delta from that substring.
The delta is simply an edit script consisting of deletion and
insertion commands that generate one revision from the other.
.PP
A delta based on a longest common substring is not necessarily minimal,
because it does not take advantage of crossing block moves.
Crossing block moves arise if two or more blocks of lines
(e.g., procedures)
appear in a different order in two revisions.
An edit script derived from a longest common substring
first deletes the shorter of the two blocks, and then reinserts it.
Heckel\u12\d
proposed an algorithm for detecting block moves, but
since the algorithm is based on heuristics,
there are conditions
under which the generated delta is far from minimal.
DSEE uses this algorithm combined with blank compression,
apparently with satisfactory overall results.
A new algorithm that is guaranteed to produce a minimal delta based on
block moves appears in Reference 13.
A future release of RCS will use this algorithm.
.PP
\fIAcknowledgements\fR:
Many people have helped make RCS a success by contributed criticisms, suggestions,
corrections, and even whole new commands (including manual pages).
The list of people is too long to be
reproduced here, but my sincere thanks for their help and
goodwill goes to all of them.
.sp
.nr VS 12p
.vs 12p
.SH
Appendix: Synopsis of RCS Operations
.LP
.IP "\fIci\fP \fB\- check in revisions\fP"
.sp 0
\fICi\fR stores the contents of a working file into the
corresponding RCS file as a new revision.
If the RCS file doesn't exist, \fIci\fR creates it.
\fICi\fR removes the working file, unless one of the options
\fI\-u\fR or \fI\-l\fR is present.
For each check-in, \fIci\fR asks for a commentary
describing the changes relative to the previous revision.
.sp 1
\fICi\fR assigns the revision number given by the \fI\-r\fR option;
if that option is missing, it derives the number from the
lock held by the user; if there is no lock and locking is not strict,
\fIci\fR increments the number of the latest revision on the trunk.
A side branch can only be started by explicitly specifying its
number with the \fI\-r\fR option during check-in.
.sp 1
\fICi\fR also determines
whether the revision to be checked in is different from the
previous one, and asks whether to proceed if not.
This facility simplifies check-in operations for large systems,
because one need not remember which files were changed.
.sp 1
The option \fI\-k\fR searches the checked in file for identification
markers containing
the attributes
revision number, check-in date, author and state, and assigns these
to the new revision rather than computing them.  This option is
useful for software distribution: Recipients of distributed software
using RCS should check in updates with the \fI\-k\fR option.
This convention guarantees that revision numbers, check-in dates,
etc., are the same at all sites.
.IP "\fIco\fP \fB\- check out revisions\fP"
.sp 0
\fICo\fR retrieves revisions according to revision number,
date, author and state attributes.  It either places the revision
into the working file, or prints it on the standard output.
\fICo\fR always expands the identification markers.
.IP "\fIident\fP \fB\- extract identification markers\fP"
.sp 0
\fIIdent\fR extracts the identification markers expanded by \fIco\fR
from any file and prints them.
.IP "\fIrcs\fP \fB\- change RCS file attributes\fP"
.sp 0
\fIRcs\fR is an administrative operation that changes access lists,
locks, unlocks, breaks locks, toggles the strict-locking feature,
sets state attributes and symbolic revision numbers, changes the
description, and deletes revisions.  A revision can
only be deleted if it is not the fork of a side branch.
.br
.ne 10
.IP "\fIrcsclean\fP \fB\- clean working directory\fP"
.sp 0
\fIRcsclean\fR removes working files that were checked out but never changed.*
.FS *
The \fIrcsclean\fP and \fIrcsfreeze\fP commands
are optional and are not always installed.
.FE
.IP "\fIrcsdiff\fP \fB\- compare revisions\fP"
.sp 0
\fIRcsdiff\fR compares two revisions and prints their
difference, using the UNIX tool \fIdiff\fR.
One of the revisions compared may be checked out.
This command is useful for finding out about changes.
.IP "\fIrcsfreeze\fP \fB\- freeze a configuration\fP"
.sp 0
\fIRcsfreeze\fR assigns the same symbolic revision number
to a given revision in all RCS files.
This command is useful for accurately recording a configuration.*
.IP "\fIrcsmerge\fP \fB\- merge revisions\fP"
.sp 0
\fIRcsmerge\fR merges two revisions, \fIrev1\fR and \fIrev2\fR,
with respect to a common ancestor.
A 3-way file comparison determines the segments of lines that
are (a) the same in all three revisions, or (b) the same in 2 revisions,
or (c) different in all three.  For all segments of type (b) where
\fIrev1\fR is the differing revision,
the segment in \fIrev1\fR replaces the corresponding segment of \fIrev2\fR.
Type (c) indicates an overlapping change, is flagged as an error, and requires user
intervention to select the correct alternative.
.IP "\fIrlog\fP \fB\- read log messages\fP"
.sp 0
\fIRlog\fR prints the log messages and other information in an RCS file.
.bp
.LP
.nr VS 12p
.vs 12p
.]<
.ds [F 1
.]-
.ds [K FELD02
.ds [K MakeArticle
.ds [A Feldman, Stuart I.
.ds [D March 1979
.ds [T Make\*-A Program for Maintaining Computer Programs
.ds [J Software\*-Practice & Experience
.ds [V 9
.ds [N 3
.ds [P 255-265
.nr [P 1
.nr [T 0
.nr [A 1
.nr [O 0
.][ 1 journal-article
.ds [F 2
.]-
.ds [K HUNT01
.ds [T An Algorithm for Differential File Comparison
.ds [A Hunt, James W.
.as [A " and McIlroy, M. D.
.ds [I Computing Science Technical Report, Bell Laboratories
.ds [R 41
.ds [D June 1976
.nr [T 0
.nr [A 1
.nr [O 0
.][ 4 tech-report
.ds [F 3
.]-
.ds [K SCCS
.ds [A Rochkind, Marc J.
.ds [D Dec. 1975
.ds [T The Source Code Control System
.ds [J IEEE Transactions on Software Engineering
.ds [V SE-1
.ds [N 4
.ds [P 364-370
.nr [P 1
.nr [T 0
.nr [A 1
.nr [O 0
.][ 1 journal-article
.ds [F 4
.]-
.ds [K TICH08
.ds [T Design, Implementation, and Evaluation of a Revision Control System
.ds [A Tichy, Walter F.
.ds [B Proceedings of the 6th International Conference on Software Engineering
.ds [I ACM, IEEE, IPS, NBS
.ds [D September 1982
.ds [P 58-67
.nr [P 1
.nr [T 0
.nr [A 1
.nr [O 0
.][ 3 article-in-book
.ds [F 5
.]-
.ds [K LEBL01
.ds [A Leblang, David B.
.as [A " and Chase, Robert P.
.ds [T Computer-Aided Software Engineering in a Distributed Workstation Environment
.ds [O Proceedings of the ACM SIGSOFT/SIGPLAN Software Engineering Symposium
.as [O " on Practical Software Development Environments.
.ds [J SIGPLAN Notices
.ds [V 19
.ds [N 5
.ds [D May 1984
.ds [P 104-112
.nr [P 1
.nr [T 0
.nr [A 1
.nr [O 0
.][ 1 journal-article
.ds [F 1
.ds [F 3
.ds [F 6
.]-
.ds [K SCCSEval
.ds [A Glasser, Alan L.
.ds [D Nov. 1978
.ds [T The Evolution of a Source Code Control System
.ds [J Software Engineering Notes
.ds [V 3
.ds [N 5
.ds [P 122-125
.nr [P 1
.ds [O Proceedings of the Software Quality and Assurance Workshop.
.nr [T 0
.nr [A 1
.nr [O 1
.][ 1 journal-article
.ds [F 5
.ds [F 7
.]-
.ds [K IBMClearCaster
.ds [A Brown, H.B.
.ds [D 1970
.ds [T The Clear/Caster System
.ds [J Nato Conference on Software Engineering, Rome
.nr [T 0
.nr [A 1
.nr [O 0
.][ 1 journal-article
.ds [F 3
.ds [F 8
.]-
.ds [K HabermannSDC
.ds [A Habermann, A. Nico
.ds [D Jan. 1979
.ds [T A Software Development Control System
.ds [I Technical Report, Carnegie-Mellon University, Department of Computer Science
.nr [T 0
.nr [A 0
.nr [O 0
.][ 2 book
.ds [F 9
.]-
.ds [K CMS
.ds [A DEC
.ds [T Code Management System
.ds [I Digital Equipment Corporation
.ds [O Document No.\ EA-23134-82
.ds [D 1982
.nr [T 0
.nr [A 0
.nr [O 0
.][ 2 book
.ds [F 10
.]-
.ds [K LAMP01
.ds [A Lampson, Butler W.
.as [A " and Schmidt, Eric E.
.ds [T Practical Use of a Polymorphic Applicative Language
.ds [B Proceedings of the 10th Symposium on Principles of Programming Languages
.ds [I ACM
.ds [P 237-255
.nr [P 1
.ds [D January 1983
.nr [T 0
.nr [A 1
.nr [O 0
.][ 3 article-in-book
.ds [F 5
.ds [F 11
.]-
.ds [K TICH07
.ds [T A Data Model for Programming Support Environments and its Application
.ds [A Tichy, Walter F.
.ds [B Automated Tools for Information System Design and Development
.ds [E Hans-Jochen Schneider and Anthony I. Wasserman
.ds [C Amsterdam
.ds [I North-Holland Publishing Company
.ds [D 1982
.nr [T 0
.nr [A 1
.nr [O 0
.][ 3 article-in-book
.ds [F 4
.ds [F 2
.ds [F 12
.]-
.ds [K HECK01
.ds [T A Technique for Isolating Differences Between Files
.ds [A Heckel, Paul
.ds [J Communications of the ACM
.ds [D April 1978
.ds [V 21
.ds [N 4
.ds [P 264-268
.nr [P 1
.nr [T 0
.nr [A 0
.nr [O 0
.][ 1 journal-article
.ds [F 13
.]-
.ds [K TICH11
.ds [T The String-to-String Correction Problem with Block Moves
.ds [A Tichy, Walter F.
.ds [D Nov. 1984
.ds [J ACM Transactions on Computer Systems
.ds [V 2
.ds [N 4
.ds [P 309-321
.nr [P 1
.nr [T 0
.nr [A 1
.nr [O 0
.][ 1 journal-article
.]>