My favorites | Sign in
Logo
          
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
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
<chapter id="svn-ch-3">
<title>Guided Tour</title>

<simplesect>

<para>Now we will go into the details of using Subversion. By the
time you reach the end of this chapter, you will be able to
perform almost all the tasks you need to use Subversion in a
normal day's work. You'll start with an initial checkout of
your code, and walk through making changes and examining those
changes. You'll also see how to bring changes made by others
into your working copy, examine them, and work through any
conflicts that might arise.</para>

<para>Note that this chapter is not meant to be an exhaustive list
of all Subversion's commands&mdash;rather, it's a conversational
introduction to the most common Subversion tasks you'll
encounter. This chapter assumes that you've read and understood
<xref linkend="svn-ch-2"/> and are familiar with the general
model of Subversion. For a complete reference of all commands,
see <xref linkend="svn-ch-9"/>.</para>

</simplesect>

<!-- ================================================================= -->
<!-- ======================== SECTION 1 ============================== -->
<!-- ================================================================= -->
<sect1 id="svn-ch-3-sect-1">
<title>Help!</title>


<para>Before reading on, here is the most important command you'll
ever need when using Subversion: <command>svn help</command>.
The Subversion command-line client is
self-documenting&mdash;at any time, a quick <command>svn help
&lt;subcommand&gt;</command> will describe the syntax, switches,
and behavior of the <command>subcommand</command>.</para>

</sect1>

<!-- ================================================================= -->
<!-- ======================== SECTION 2 ============================== -->
<!-- ================================================================= -->
<sect1 id="svn-ch-3-sect-2">
<title>Import</title>

<para>You use <command>svn import</command> to import a new
project into a Subversion repository. While this is most likely
the very first thing you will do when you set up your Subversion
server, it's not something that happens very often. For a
detailed description of import, see <xref
linkend="svn-ch-3-sect-7.3"/> later in this chapter.
</para>

</sect1>

<!-- ================================================================= -->
<!-- ======================== SECTION 3 ============================== -->
<!-- ================================================================= -->
<sect1 id="svn-ch-3-sect-3">
<title>Revisions: Numbers, Keywords, and Dates, Oh My!</title>

<para>Before we go on, you should know a bit about how to identify
a particular revision in your repository. As you learned in
<xref linkend="svn-ch-2-sect-3.2"/>, a revision is a
<quote>snapshot</quote> of the repository at a particular moment
in time. As you continue to commit and grow your repository,
you need a mechanism for identifying these snapshots.</para>

<para>You specify these revisions by using the
<option>--revision</option> (<option>-r</option>) switch plus
the revision you want (<command>svn --revision REV</command>) or
you can specify a range by separating two revisions with a colon
(<command>svn --revision REV1:REV2</command>). And Subversion
lets you refer to these revisions by number, keyword, or
date.</para>

<sect2 id="svn-ch-3-sect-3.1">
<title>Revision Numbers</title>

<para>When you create a new Subversion repository, it begins its
life at revision zero and each successive commit increases the
revision number by one. After your commit completes, the
Subversion client informs you of the new revision
number:</para>

<screen>
$ svn commit --message "Corrected number of cheese slices."
Sending sandwich.txt
Transmitting file data .
Committed revision 3.
</screen>

<para>If at any point in the future you want to refer to that
revision (we'll see how and why we might want to do that later
in this chapter), you can refer to it as
<quote>3</quote>.</para>

</sect2>

<sect2 id="svn-ch-3-sect-3.2">
<title>Revision Keywords</title>

<para>The Subversion client understands a number of
<firstterm>revision keywords</firstterm>. These keywords
can be used instead of integer arguments to the
<option>--revision</option> switch, and are resolved into
specific revision numbers by Subversion:</para>

<note>
<para>Each directory in your working copy contains an
administrative subdirectory called
<filename>.svn</filename>. For every file in a directory,
Subversion keeps a copy of each file in the administrative
area. This copy is an unmodified (no keyword expansion, no
end-of-line translation, no nothing) copy of the file as it
existed in the last revision (called the <quote>BASE</quote>
revision) that you updated it to in your working copy. We
refer to this file as the <firstterm>pristine
copy</firstterm> or <firstterm>text-base</firstterm> version
of your file, and it's always an exact byte-for-byte copy of
the file as it exists in the repository.</para>
</note>

<variablelist>

<varlistentry>
<term>HEAD</term>
<listitem>
<para>The latest revision in the repository.</para>
</listitem>
</varlistentry>

<varlistentry>
<term>BASE</term>
<listitem>
<para>The <quote>pristine</quote> revision of an item in a
working copy.</para>
</listitem>
</varlistentry>

<varlistentry>
<term>COMMITTED</term>
<listitem>
<para>The last revision in which an item changed before (or
at) <literal>BASE</literal>.</para>
</listitem>
</varlistentry>

<varlistentry>
<term>PREV</term>
<listitem>
<para>The revision just <emphasis>before</emphasis> the last
revision in which an item changed. (Technically,
<literal>COMMITTED</literal> - 1.)</para>
</listitem>
</varlistentry>

</variablelist>

<note>
<para><literal>PREV</literal>, <literal>BASE</literal>, and
<literal>COMMITTED</literal> can be used to refer to local
paths, but not to URLs.</para>
</note>

<para>Here are some examples of revision keywords in action.
Don't worry if the commands don't make sense yet; we'll be
explaining these commands as we go through the chapter:</para>

<screen>
$ svn diff --revision PREV:COMMITTED foo.c
# shows the last change committed to foo.c

$ svn log --revision HEAD
# shows log message for the latest repository commit

$ svn diff --revision HEAD
# compares your working file (with local mods) to the latest version
# in the repository.

$ svn diff --revision BASE:HEAD foo.c
# compares your <quote>pristine</quote> foo.c (no local mods) with the
# latest version in the repository

$ svn log --revision BASE:HEAD
# shows all commit logs since you last updated

$ svn update --revision PREV foo.c
# rewinds the last change on foo.c.
# (foo.c's working revision is decreased.)
</screen>

<para>These keywords allow you to perform many common (and
helpful) operations without having to look up specific
revision numbers or remember the exact revision of your
working copy.</para>

</sect2>

<sect2 id="svn-ch-3-sect-3.3">
<title>Revision Dates</title>

<para>Anywhere that you specify a revision number or revision
keyword, you can also specify a date by specifying the date
inside curly braces <quote>{}</quote>. You can even access
a range of changes in the repository using both dates and
revisions together!</para>

<para>Here are examples of the date formats that Subversion
accepts. Remember to use quotes around any date that contains
spaces.</para>

<screen>
$ svn checkout --revision {2002-02-17}
$ svn checkout --revision {15:30}
$ svn checkout --revision {15:30:00.200000}
$ svn checkout --revision {"2002-02-17 15:30"}
$ svn checkout --revision {"2002-02-17 15:30 +0230"}
$ svn checkout --revision {2002-02-17T15:30}
$ svn checkout --revision {2002-02-17T15:30Z}
$ svn checkout --revision {2002-02-17T15:30-04:00}
$ svn checkout --revision {20020217T1530}
$ svn checkout --revision {20020217T1530Z}
$ svn checkout --revision {20020217T1530-0500}
&hellip;
</screen>

<para>When you specify a date as a revision, Subversion finds
the most recent revision of the repository as of that
date:</para>

<screen>
$ svn log --revision {2002-11-28}
------------------------------------------------------------------------
r12 | ira | 2002-11-27 12:31:51 -0600 (Wed, 27 Nov 2002) | 6 lines
&hellip;
</screen>

<sidebar>
<title>Is Subversion a Day Early?</title>

<para>If you specify a single date as a revision without
specifying a time of day (for example
<literal>2002-11-27</literal>), you may think that Subversion
should give you the last revision that took place on the
27th of November. Instead, you'll get back a revision from
the 26th, or even earlier. Remember that Subversion will
find the <emphasis>most recent revision of the
repository</emphasis> as of the date you give. If you give
a date without a timestamp, like
<literal>2002-11-27</literal>, Subversion assumes a time of
00:00:00, so looking for the most recent revision won't
return anything on the day of the 27th.</para>

<para>If you want to include the 27th in your search, you can
either specify the 27th with the time (<literal>{"2002-11-27
23:59"}</literal>), or just specify the next day
(<literal>{2002-11-28}</literal>).</para>

</sidebar>

<para>You can also use a range of dates. Subversion will find
all revisions between both dates, inclusive:</para>

<screen>
$ svn log --revision {2002-11-20}:{2002-11-29}
&hellip;
</screen>

<para>As we pointed out, you can also mix dates and revisions:</para>

<screen>
$ svn log --revision {2002-11-20}:4040
</screen>

<para>Users should be aware of a subtlety that can become quite
a stumblingblock when dealing with dates in Subversion. Since
the timestamp of a revision is stored as a property of the
revision&mdash;an unversioned, modifiable
property&mdash;revision timestamps can be changed to represent
complete falsifications of true chronology, or even removed
altogether. This will wreak havoc on the internal
date-to-revision conversion that Subversion performs.</para>

</sect2>

</sect1>

<!-- ================================================================= -->
<!-- ======================== SECTION 4 ============================== -->
<!-- ================================================================= -->
<sect1 id="svn-ch-3-sect-4">
<title>Initial Checkout</title>

<para>Most of the time, you will start using a Subversion
repository by doing a <firstterm>checkout</firstterm> of your
project. Checking out a repository creates a copy of it on your
local machine. This copy contains the <literal>HEAD</literal>
(latest revision) of the Subversion repository that you specify
on the command line:</para>


<screen>
$ svn checkout http://svn.collab.net/repos/svn/trunk
A trunk/subversion.dsw
A trunk/svn_check.dsp
A trunk/COMMITTERS
A trunk/configure.in
A trunk/IDEAS
&hellip;
Checked out revision 2499.
</screen>

<sidebar>
<title>Repository Layout</title>

<para>If you're wondering what <literal>trunk</literal> is all
about in the above URL, it's part of the way we recommend
you lay out your Subversion repository which we'll talk a lot
more about in <xref linkend="svn-ch-4"/>.</para>

</sidebar>

<para>Although the above example checks out the trunk directory,
you can just as easily check out any deep subdirectory of a
repository by specifying the subdirectory in the checkout
URL:</para>

<screen>
$ svn checkout http://svn.collab.net/repos/svn/trunk/doc/book/tools
A tools/readme-dblite.html
A tools/fo-stylesheet.xsl
A tools/svnbook.el
A tools/dtd
A tools/dtd/dblite.dtd
&hellip;
Checked out revision 2499.
</screen>

<para>Since Subversion uses a <quote>copy-modify-merge</quote>
model instead of <quote>lock-modify-unlock</quote> (see <xref
linkend="svn-ch-2"/>), you're already able to start making
changes to the files and directories in your working copy. Your
working copy is just like any other collection of files and
directories on your system. You can edit and change them, move
them around, you can even delete the entire working copy and
forget about it.</para>

<note>
<para>While your working copy is <quote>just like any other
collection of files and directories on your system</quote>,
you need to let Subversion know if you're going to be
rearranging anything inside of your working copy. If you
want to copy or move an item in a working copy, you should
use <command>svn copy</command> or <command>svn
move</command> instead of the copy and move commands
provided by your operating system. We'll talk more about
them later in this chapter.</para>
</note>

<para>Unless you're ready to commit a new file or directory, or
changes to existing ones, there's no need to further notify the
Subversion server that you've done anything.</para>

<sidebar>
<title>What's with the <filename>.svn</filename> directory?</title>

<para>Every directory in a working copy contains an
administrative area, a subdirectory named
<filename>.svn</filename>. Usually, directory listing
commands won't show this subdirectory, but it is nevertheless
an important directory. Whatever you do, don't delete or
change anything in the administrative area! Subversion
depends on it to manage your working copy.</para>

</sidebar>

<para>While you can certainly check out a working copy with the
URL of the repository as the only argument, you can also specify
a directory after your repository URL. This places your working
copy into the new directory that you name. For example:</para>

<screen>
$ svn checkout http://svn.collab.net/repos/svn/trunk subv
A subv/subversion.dsw
A subv/svn_check.dsp
A subv/COMMITTERS
A subv/configure.in
A subv/IDEAS
&hellip;
Checked out revision 2499.
</screen>

<para>That will place your working copy in a directory named
<literal>subv</literal> instead of a directory named
<literal>trunk</literal> as we did previously.</para>

</sect1>

<!-- ================================================================= -->
<!-- ======================== SECTION 5 ============================== -->
<!-- ================================================================= -->
<sect1 id="svn-ch-3-sect-5">
<title>Basic Work Cycle</title>

<para>Subversion has numerous features, options, bells and whistles, but on
a day-to-day basis, odds are that you will only use a few of them. In
this section we'll run through the most common things that you might
find yourself doing with Subversion in the course of a day's work.</para>

<para>The typical work cycle looks like this:</para>

<itemizedlist>
<listitem>
<para>Update your working copy</para>
<itemizedlist>
<listitem>
<para><command>svn update</command></para>
</listitem>
</itemizedlist>

</listitem>

<listitem>
<para>Make changes</para>
<itemizedlist>
<listitem>
<para><command>svn add</command></para>
</listitem>
<listitem>
<para><command>svn delete</command></para>
</listitem>
<listitem>
<para><command>svn copy</command></para>
</listitem>
<listitem>
<para><command>svn move</command></para>
</listitem>
</itemizedlist>
</listitem>

<listitem>
<para>Examine your changes</para>
<itemizedlist>
<listitem>
<para><command>svn status</command></para>
</listitem>
<listitem>
<para><command>svn diff</command></para>
</listitem>
<listitem>
<para><command>svn revert</command></para>
</listitem>
</itemizedlist>
</listitem>

<listitem>
<para>Merge others' changes</para>
<itemizedlist>
<listitem>
<para><command>svn merge</command></para>
</listitem>
<listitem>
<para><command>svn resolved</command></para>
</listitem>
</itemizedlist>
</listitem>

<listitem>
<para>Commit your changes</para>
<itemizedlist>
<listitem>
<para><command>svn commit</command></para>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>

<sect2 id="svn-ch-3-sect-4.1">
<title>Update Your Working Copy</title>

<para>When working on a project with a team, you'll want to
update your working copy to receive any changes made since
your last update by other developers on the project. Use
<command>svn update</command> to bring your working copy into
sync with the latest revision in the repository.</para>

<screen>
$ svn update
U foo.c
U bar.c
Updated to revision 2.
</screen>

<para>In this case, someone else checked in modifications to
both <filename>foo.c</filename> and <filename>bar.c</filename>
since the last time you updated, and Subversion has updated
your working copy to include those changes.</para>

<para>Let's examine the output of <command>svn update</command>
a bit more. When the server sends changes to your working
copy, a letter code is displayed next to each item to let you
know what actions Subversion performed to bring your working
copy up-to-date:</para>

<variablelist>

<varlistentry>
<term><computeroutput>U foo</computeroutput></term>
<listitem>
<para>File <filename>foo</filename> was
<computeroutput>U</computeroutput>pdated (received changes
from the server).</para>
</listitem>
</varlistentry>

<varlistentry>
<term><computeroutput>A foo</computeroutput></term>
<listitem>
<para>File or directory <filename>foo</filename> was
<computeroutput>A</computeroutput>dded to your working
copy.</para>
</listitem>
</varlistentry>

<varlistentry>
<term><computeroutput>D foo</computeroutput></term>
<listitem>
<para>File or directory <filename>foo</filename> was
<computeroutput>D</computeroutput>eleted from your working
copy.</para>
</listitem>
</varlistentry>

<varlistentry>
<term><computeroutput>R foo</computeroutput></term>
<listitem>
<para>File or directory <filename>foo</filename> was
<computeroutput>R</computeroutput>eplaced in your working
copy; that is, <filename>foo</filename> was deleted, and a
new item with the same name was added. While they may have
the same name, the repository considers them to be distinct
objects with distinct histories.</para>
</listitem>
</varlistentry>

<varlistentry>
<term><computeroutput>G foo</computeroutput></term>
<listitem>
<para>File <filename>foo</filename> received new changes
from the repository, but your local copy of the file had
your modifications. Either the changes did not intersect,
or the changes were exactly the same as your local
modifications, so Subversion has successfully
mer<computeroutput>G</computeroutput>ed the repository's
changes into the file without a problem.</para>
</listitem>
</varlistentry>

<varlistentry>
<term><computeroutput>C foo</computeroutput></term>
<listitem>
<para>File <filename>foo</filename> received
<computeroutput>C</computeroutput>onflicting changes from
the server. The changes from the server directly overlap
your own changes to the file. No need to panic, though.
This overlap needs to be resolved by a human (you); we
discuss this situation later in this chapter.</para>
</listitem>
</varlistentry>

</variablelist>

</sect2>

<sect2 id="svn-ch-3-sect-4.2">
<title>Make Changes to Your Working Copy</title>

<para>Now you can get to work and make changes in your
working copy. It's usually most convenient to decide on a
particular change (or set of changes) to make, such as writing
a new feature, fixing a bug, etc. The Subversion commands
that you will use here are <command>svn add</command>,
<command>svn delete</command>, <command>svn copy</command>,
and <command>svn move</command>. However, if you are merely
editing files that are already in Subversion, you may not need
to use any of these commands until you commit. Changes you can
make to your working copy:</para>

<variablelist>

<varlistentry>
<term>File changes</term>
<listitem>
<para>This is the simplest sort of change. You don't need
to tell Subversion that you intend to change a file;
just make your changes. Subversion will be able to
automatically detect which files have been
changed.</para>
</listitem>
</varlistentry>

<varlistentry>
<term>Tree changes</term>
<listitem>
<para>You can ask Subversion to <quote>mark</quote> files
and directories for scheduled removal, addition,
copying, or moving. While these changes may take place
immediately in your working copy, no additions or
removals will happen in the repository until you commit
them.</para>
</listitem>
</varlistentry>

</variablelist>

<para>To make file changes, use your text editor, word
processor, graphics program, or whatever tool you would
normally use. Subversion handles binary files just as easily
as it handles text files&mdash;and just as efficiently
too.</para>

<para>Here is an overview of the four Subversion subcommands
that you'll use most often to make tree changes (we'll cover
<command>svn import</command> and <command>svn mkdir</command>
later).</para>

<variablelist>

<varlistentry>
<term><command>svn add foo</command></term>
<listitem>
<para>Schedule <filename>foo</filename> to be added to the
repository. When you next commit,
<filename>foo</filename> will become a child of its
parent directory. Note that if <filename>foo</filename>
is a directory, everything underneath <filename>foo</filename>
will be scheduled for addition. If you only want to
schedule <filename>foo</filename> itself, pass the
<option>--non-recursive</option> (<option>-N</option>)
switch.</para>
</listitem>
</varlistentry>

<varlistentry>
<term><command>svn delete foo</command></term>
<listitem>
<para>Schedule <filename>foo</filename> to be deleted from
the repository. If <filename>foo</filename> is a file,
it is immediately deleted from your working copy. If
<filename>foo</filename> is a directory, it is not
deleted, but Subversion schedules it for deletion. When
you commit your changes, <filename>foo</filename> will
be removed from your working copy and the repository.
<footnote><para>Of course, nothing is ever totally
deleted from the repository&mdash;just from the
<literal>HEAD</literal> of the repository. You can get
back anything you delete by checking out (or updating
your working copy) a revision earlier than the one in
which you deleted it.</para> </footnote></para>
</listitem>
</varlistentry>

<varlistentry>
<term><command>svn copy foo bar</command></term>
<listitem>
<para>Create a new item <filename>bar</filename> as a
duplicate of <filename>foo</filename>.
<filename>bar</filename> is automatically scheduled for
addition. When <filename>bar</filename> is added to the
repository on the next commit, its copy history is
recorded (as having originally come from
<filename>foo</filename>). <command>svn copy</command>
does not create intermediate directories.</para>
</listitem>
</varlistentry>

<varlistentry>
<term><command>svn move foo bar</command></term>
<listitem>
<para>This command is exactly the same as running
<command>svn copy foo bar; svn delete foo</command>.
That is, <filename>bar</filename> is scheduled for
addition as a copy of <filename>foo</filename>, and
<filename>foo</filename> is scheduled for removal.
<command>svn move</command> does not create intermediate
directories.</para>
</listitem>
</varlistentry>

</variablelist>

<sidebar>
<title>Changing the Repository Without a Working Copy</title>

<!-- ### pll - Fri 07 Feb 2003 12:55:07 -->
<!-- I find this sidebar rather confusing here, since you really -->
<!-- haven't gone through explaining the svn command line syntax -->
<!-- anywhere. Maybe a short section explaining that subversion -->
<!-- can be used both in networked and non-networked environments, -->
<!-- and which types of commands need URLs, etc. This should -->
<!-- probably be in chapter 2 (around the "Subversion in action" -->
<!-- though, so that this sidebar makes more sense. -->

<para>Earlier in this chapter, we said that you have to commit
any changes that you make in order for the repository to
reflect these changes. That's not entirely true&mdash;there
<emphasis>are</emphasis> some use-cases that immediately
commit tree changes to the repository. This only happens
when a subcommand is operating directly on a URL, rather
than on a working-copy path. In particular, specific uses
of <command>svn mkdir</command>, <command>svn
copy</command>, <command>svn move</command>, and
<command>svn delete</command> can work with URLs.</para>

<para>URL operations behave in this manner because commands
that operate on a working copy can use the working copy as a
sort of <quote>staging area</quote> to set up your changes
before committing them to the repository. Commands that
operate on URLs don't have this luxury, so when you operate
directly on a URL, any of the above actions represent an
immediate commit.</para>

</sidebar>

</sect2>

<sect2 id="svn-ch-3-sect-4.3">
<title>Examine Your Changes</title>

<para>Once you've finished making changes, you need to commit
them to the repository, but before you do so, it's usually a
good idea to take a look at exactly what you've changed. By
examining your changes before you commit, you can make a
more accurate log message. You may also discover that
you've inadvertently changed a file, and this gives you a
chance to revert those changes before committing.
Additionally, this is a good opportunity to review and
scrutinize changes before publishing them. You can see
exactly what changes you've made by using <command>svn
status</command>, <command>svn diff</command>, and
<command>svn revert</command>. You will usually use the first
two commands to find out what files have changed in your
working copy, and then perhaps the third to revert some (or
all) of those changes.</para>

<!-- pll - Fri 07 Feb 2003 12:55:07 -->
<!-- I find this following paragraph a little unclear. Mostly for -->
<!-- the same reasons as I found the sidebar above unclear. There -->
<!-- hasn't been much discussion of the Subversion architecture, and -->
<!-- therefore, nothing has been clearly stated wrt the fact that the -->
<!-- repository may not be local. -->

<para>Subversion has been optimized to help you with this task,
and is able to do many things without communicating with the
repository. In particular, your working copy contains a
secret cached <quote>pristine</quote> copy of each version
controlled file within the <filename>.svn</filename> area.
Because of this, Subversion can quickly show you how your
working files have changed, or even allow you to undo your
changes without contacting the repository.</para>

<sect3 id="svn-ch-3-sect-4.3.1">
<title><command>svn status</command></title>

<para>You'll probably use the <command>svn status</command>
command more than any other Subversion command.</para>

<sidebar>
<title>CVS Users: Hold That Update!</title>

<para>You're probably used to using <command>cvs
update</command> to see what changes you've made to your
working copy. <command>svn status</command> will give you
all the information you need regarding what has changed in
your working copy&mdash;without accessing the repository
or potentially incorporating new changes published by
other users.</para>

<para>In Subversion, <command>update</command> does just
that&mdash;it updates your working copy with any changes
committed to the repository since the last time you've
updated your working copy. You'll have to break the habit
of using the <command>update</command> command to see what
local modifications you've made.</para>

</sidebar>

<para>If you run <command>svn status</command> at the top of
your working copy with no arguments, it will detect all file
and tree changes you've made. This example is designed to
show all the different status codes that <command>svn
status</command> can return. (Note that the text following
<literal>#</literal> in the following example is not
actually printed by <command>svn status</command>.)</para>

<screen>
$ svn status
L abc.c # svn has a lock in its .svn directory for abc.c
M bar.c # the content in bar.c has local modifications
M baz.c # baz.c has property but no content modifications
X 3rd_party # this dir is part of an externals definition
? foo.o # svn doesn't manage foo.o
! some_dir # svn manages this, but it's either missing or incomplete
~ qux # versioned as dir, but is file, or vice versa
I .screenrc # this file is ignored
A + moved_dir # added with history of where it came from
M + moved_dir/README # added with history and has local modifications
D stuff/fish.c # this file is scheduled for deletion
A stuff/loot/bloo.h # this file is scheduled for addition
C stuff/loot/lump.c # this file has conflicts from an update
S stuff/squawk # this file or dir has been switched to a branch
&hellip;
</screen>

<para>In this output format <command>svn status</command>
prints five columns of characters, followed by several
whitespace characters, followed by a file or directory name.
The first column tells the status of a file or directory
and/or its contents. The codes printed here are:</para>


<variablelist>

<varlistentry>
<term><computeroutput>A file_or_dir</computeroutput></term>
<listitem>
<para>The file or directory
<filename>file_or_dir</filename> has been scheduled for
addition into the repository.
</para>
</listitem>
</varlistentry>

<varlistentry>
<term><computeroutput>C file</computeroutput></term>
<listitem>
<para>The file <filename>file</filename> is in a state of
conflict. That is, changes received from the server
during an update overlap with local changes that you
have in your working copy. You must resolve this
conflict before committing your changes to the
repository.</para>
</listitem>
</varlistentry>

<varlistentry>
<term><computeroutput>D file_or_dir</computeroutput></term>
<listitem>
<para>The file or directory
<filename>file_or_dir</filename> has been scheduled for
deletion from the repository.</para>
</listitem>
</varlistentry>

<varlistentry>
<term><computeroutput>M file</computeroutput></term>
<listitem>
<para>The contents of the file <filename>file</filename> have
been modified.</para>
</listitem>
</varlistentry>

<varlistentry>
<term><computeroutput>X dir</computeroutput></term>
<listitem>
<para>The directory <filename>dir</filename> is
unversioned, but is related to a Subversion externals
definition. To find out more about externals
definitions, see <xref linkend="svn-ch-7-sect-3"/>.</para>
</listitem>
</varlistentry>

<varlistentry>
<term><computeroutput>? file_or_dir</computeroutput></term>
<listitem>
<para>The file or directory
<filename>file_or_dir</filename> is not under version
control. You can silence the question marks by either
passing the <option>--quiet</option>
(<option>-q</option>) switch to <command>svn
status</command>, or by setting the
<literal>svn:ignore</literal> property on the parent
directory. For more information on ignored files, see
<xref linkend="svn-ch-7-sect-2.3.3" />.</para>

</listitem>
</varlistentry>

<varlistentry>
<term><computeroutput>! file_or_dir</computeroutput></term>
<listitem>
<para>The file or directory
<filename>file_or_dir</filename> is under version
control but is missing or somehow incomplete. The
item can be missing if it's removed using a
non-Subversion command. In the case of a directory,
it can be incomplete if you happened to interrupt a
checkout or update. A quick <command>svn
update</command> will refetch the file or directory
from the repository, or <command>svn revert
file</command> will restore a missing file.</para>
</listitem>
</varlistentry>

<varlistentry>
<term><computeroutput>~ file_or_dir</computeroutput></term>
<listitem>
<para>The file or directory
<filename>file_or_dir</filename> is in the repository as
one kind of object, but what's actually in your working
copy is some other kind. For example, Subversion might
have a file in the repository, but you removed the file
and created a directory in its place, without using the
<command>svn delete</command> or <command>svn add</command>
commands.</para>
</listitem>
</varlistentry>

<varlistentry>
<term><computeroutput>I file_or_dir</computeroutput></term>
<listitem>
<para>Subversion is <quote>ignoring</quote> the file or
directory <filename>file_or_dir</filename>, probably
because you told it to. For more information on ignored
files, see <xref linkend="svn-ch-7-sect-2.3.3"/>.
Note that this symbol only shows up if you pass the
<option>--no-ignore</option> option to <command>svn
status</command>.</para>
</listitem>
</varlistentry>

</variablelist>

<para>The second column tells the status of a file or
directory's properties (see <xref
linkend="svn-ch-7-sect-2"></xref> for more information on
properties). If an <computeroutput>M</computeroutput>
appears in the second column, then the properties have been
modified, otherwise a whitespace will be printed.</para>

<para>The third column will only show whitespace or an
<computeroutput>L</computeroutput> which means that
Subversion has locked the item in
the <filename>.svn</filename> working area. You will see an
<computeroutput>L</computeroutput> if you run <command>svn
status</command> in a directory where an <command>svn
commit</command> is in progress&mdash;perhaps when you are
editing the log message. If Subversion is not running, then
presumably Subversion was interrupted and the lock needs to
be cleaned up by running <command>svn cleanup</command>
(more about that later in this chapter).</para>

<para>The fourth column will only show whitespace or a
<computeroutput>+</computeroutput> which means that the file
or directory is scheduled to be added or modified with
additional attached history. This typically happens when you
<command>svn move</command> or <command>svn copy</command> a file
or directory. If you see
<computeroutput>A&nbsp;&nbsp;+</computeroutput>, this means
the item is scheduled for addition-with-history. It could be
a file, or the root of a copied directory.
<computeroutput>+</computeroutput>
means the item is part of a subtree scheduled for
addition-with-history, i.e. some parent got copied, and it's
just coming along for the ride.
<computeroutput>M&nbsp;&nbsp;+</computeroutput> means the item
is part of a subtree scheduled for addition-with-history,
<emphasis>and</emphasis> it has local modifications. When you
commit, first the parent will be added-with-history (copied),
which means this file will automatically exist in the copy.
Then the local modifications will be uploaded into the
copy.</para>

<para>The fifth column will only show whitespace or an
<computeroutput>S</computeroutput>. This signifies that the
file or directory has been switched from the path of the
rest of the working copy (using <command>svn
switch</command>) to a branch.</para>

<para>If you pass a specific path to <command>svn
status</command>, it gives you information about that item
alone:</para>

<screen>
$ svn status stuff/fish.c
D stuff/fish.c
</screen>

<para><command>svn status</command> also has a
<option>--verbose</option> (<option>-v</option>) switch,
which will show you the status of <emphasis>every</emphasis>
item in your working copy, even if it has not been
changed:</para>

<screen>
$ svn status --verbose
M 44 23 sally README
44 30 sally INSTALL
M 44 20 harry bar.c
44 18 ira stuff
44 35 harry stuff/trout.c
D 44 19 ira stuff/fish.c
44 21 sally stuff/things
A 0 ? ? stuff/things/bloo.h
44 36 harry stuff/things/gloo.c
</screen>

<para>This is the <quote>long form</quote> output of
<command>svn status</command>. The first column remains
the same, but the second column shows the working-revision of
the item. The third and fourth columns show the revision in
which the item last changed, and who changed it.</para>

<para>None of the above invocations to <command>svn
status</command> contact the repository, they work only
locally by comparing the metadata in the
<filename>.svn</filename> directory with the working copy.
Finally, there is the <option>--show-updates</option>
(<option>-u</option>) switch, which contacts the repository
and adds information about things that are
out-of-date:</para>

<screen>
$ svn status --show-updates --verbose
M * 44 23 sally README
M 44 20 harry bar.c
* 44 35 harry stuff/trout.c
D 44 19 ira stuff/fish.c
A 0 ? ? stuff/things/bloo.h
Status against revision: 46
</screen>

<para>Notice the two asterisks: if you were to run
<command>svn update</command> at this point, you would
receive changes to <filename>README</filename>
and <filename>trout.c</filename>. This tells you some very
useful information&mdash;you'll need to update and get the
server changes on <filename>README</filename> before you
commit, or the repository will reject your commit for being
out-of-date. (More on this subject later.)</para>

</sect3>

<sect3 id="svn-ch-3-sect-4.3.2">
<title><command>svn diff</command></title>

<para>Another way to examine your changes is with the
<command>svn diff</command> command. You can find out
<emphasis>exactly</emphasis> how you've modified things by
running <command>svn diff</command> with no arguments, which
prints out file changes in unified diff
format:<footnote><para>Subversion uses its internal diff
engine, which produces unified diff format, by default. If
you want diff output in a different format, specify an
external diff program using <option>--diff-cmd</option> and
pass any flags you'd like to it using the
<option>--extensions</option> switch. For example, to see
local differences in file <filename>foo.c</filename> in
context output format while ignoring whitespace changes, you
might run <command>svn diff --diff-cmd /usr/bin/diff
--extensions '-bc' foo.c</command>.</para>
</footnote></para>

<screen>
$ svn diff
Index: bar.c
===================================================================
--- bar.c (revision 3)
+++ bar.c (working copy)
@@ -1,7 +1,12 @@
+#include &lt;sys/types.h&gt;
+#include &lt;sys/stat.h&gt;
+#include &lt;unistd.h&gt;
+
+#include &lt;stdio.h&gt;

int main(void) {
- printf("Sixty-four slices of American Cheese...\n");
+ printf("Sixty-five slices of American Cheese...\n");
return 0;
}

Index: README
===================================================================
--- README (revision 3)
+++ README (working copy)
@@ -193,3 +193,4 @@
+Note to self: pick up laundry.

Index: stuff/fish.c
===================================================================
--- stuff/fish.c (revision 1)
+++ stuff/fish.c (working copy)
-Welcome to the file known as 'fish'.
-Information on fish will be here soon.

Index: stuff/things/bloo.h
===================================================================
--- stuff/things/bloo.h (revision 8)
+++ stuff/things/bloo.h (working copy)
+Here is a new file to describe
+things about bloo.
</screen>

<para>The <command>svn diff</command> command produces this
output by comparing your working files against the cached
<quote>pristine</quote> copies within the
<filename>.svn</filename> area. Files scheduled for
addition are displayed as all added-text, and files
scheduled for deletion are displayed as all deleted
text.</para>

<para>Output is displayed in <firstterm>unified diff
format</firstterm>. That is, removed lines are prefaced
with a <literal>-</literal> and added lines are prefaced
with a <literal>+</literal>. <command>svn diff</command>
also prints filename and offset information useful to the
<command>patch</command> program, so you can generate
<quote>patches</quote> by redirecting the diff output to a
file:</para>

<screen>
$ svn diff &gt; patchfile
</screen>

<para>You could, for example, email the patchfile to another
developer for review or testing prior to commit.</para>

</sect3>

<sect3 id="svn-ch-3-sect-4.3.3">
<title><command>svn revert</command></title>

<para>Now suppose you see the above diff output, and realize
that your changes to <filename>README</filename> are a
mistake; perhaps you accidentally typed that text into the
wrong file in your editor.</para>

<para>This is a perfect opportunity to use <command>svn
revert</command>.</para>

<screen>
$ svn revert README
Reverted 'README'
</screen>

<para>Subversion reverts the file to its pre-modified state by
overwriting it with the cached <quote>pristine</quote> copy
from the <filename>.svn</filename> area. But also note that
<command>svn revert</command> can undo
<emphasis>any</emphasis> scheduled operations&mdash;for
example, you might decide that you don't want to add a new
file after all:</para>

<screen>
$ svn status foo
? foo

$ svn add foo
A foo

$ svn revert foo
Reverted 'foo'

$ svn status foo
? foo
</screen>

<note>
<para><command>svn revert</command>
<replaceable>ITEM</replaceable> has exactly the same effect as
deleting <replaceable>ITEM</replaceable> from your working
copy and then running <command>svn update -r BASE</command>
<replaceable>ITEM</replaceable>. However, if you're reverting
a file, <command>svn revert</command> has one very noticeable
difference&mdash;it doesn't have to communicate with the
repository to restore your file.</para>
</note>

<para>Or perhaps you mistakenly removed a file from version
control:</para>

<screen>
$ svn status README
README

$ svn delete README
D README

$ svn revert README
Reverted 'README'

$ svn status README
README
</screen>

</sect3>

<sidebar>
<title>Look Ma! No Network!</title>

<para>All three of these commands (<command>svn
status</command>, <command>svn diff</command>, and
<command>svn revert</command>) can be used without any
network access. This makes it easy to manage your
changes-in-progress when you are somewhere without a network
connection, such as traveling on an airplane, riding a
commuter train or hacking on the beach.</para>

<para>Subversion does this by keeping private caches of
pristine versions of each versioned file inside of the
<filename>.svn</filename> administrative areas. This allows
Subversion to report&mdash;and revert&mdash;local
modifications to those files <emphasis>without network
access</emphasis>. This cache (called the
<quote>text-base</quote>) also allows Subversion to send the
user's local modifications during a commit to the server as
a compressed <firstterm>delta</firstterm> (or
<quote>difference</quote>) against the pristine version.
Having this cache is a tremendous benefit&mdash;even if you
have a fast net connection, it's much faster to send only a
file's changes rather than the whole file to the server. At
first glance, this might not seem that important, but
imagine the repercussions if you try to commit a one line
change to a 400MB file and have to send the whole file to
the server!</para>
</sidebar>

</sect2>

<sect2 id="svn-ch-3-sect-4.4">
<title>Resolve Conflicts (Merging Others' Changes)</title>

<para>We've already seen how <command>svn status -u</command>
can predict conflicts. Suppose you run <command>svn
update</command> and some interesting things occur:</para>

<screen>
$ svn update
U INSTALL
G README
C bar.c
Updated to revision 46.
</screen>

<para>The <computeroutput>U</computeroutput> and
<computeroutput>G</computeroutput> codes are no cause for
concern; those files cleanly absorbed changes from the
repository. The files marked with
<computeroutput>U</computeroutput> contained no local changes
but were <computeroutput>U</computeroutput>pdated with changes
from the repository. The <computeroutput>G</computeroutput>
stands for mer<computeroutput>G</computeroutput>ed, which
means that the file had local changes to begin with, but the
changes coming from the repository didn't overlap in any
way.</para>

<para>But the <computeroutput>C</computeroutput> stands for
conflict. This means that the changes from the server overlapped
with your own, and now you have to manually choose between
them.</para>

<para>Whenever a conflict occurs, three things occur to assist
you in noticing and resolving that conflict:</para>

<itemizedlist>

<listitem>
<para>Subversion prints a <computeroutput>C</computeroutput>
during the update, and remembers that the file is in a
state of conflict.</para>
</listitem>

<listitem>
<para>Subversion places <firstterm>conflict
markers</firstterm>&mdash;special strings of text which
delimit the <quote>sides</quote> of the
conflict&mdash;into the file to visibly demonstrate the
overlapping areas.</para>
</listitem>

<listitem>
<para>For every conflicted file, Subversion places three
extra files in your working copy:</para>

<variablelist>

<varlistentry>
<term><filename>filename.mine</filename></term>
<listitem>
<para> This is your file as it existed in your working
copy before you updated your working copy&mdash;that
is, without conflict markers. This file has your
latest changes in it and nothing else.</para>
</listitem>
</varlistentry>

<varlistentry>
<term><filename>filename.rOLDREV</filename></term>
<listitem>
<para>This is the file that was the
<literal>BASE</literal> revision before you updated
your working copy. That is, the file that you
checked out before you made your latest
edits.</para>
</listitem>
</varlistentry>

<varlistentry>
<term><filename>filename.rNEWREV</filename></term>
<listitem>
<para>This is the file that your Subversion client
just received from the server when you updated your
working copy. This file corresponds to the
<literal>HEAD</literal> revision of the
repository.</para>
</listitem>
</varlistentry>

</variablelist>

<para>Here <literal>OLDREV</literal> is the revision number
of the file in your <filename>.svn</filename> directory
and <literal>NEWREV</literal> is the revision number of
the repository <literal>HEAD</literal>.
</para>
</listitem>

</itemizedlist>

<para>For example, Sally makes changes to the file
<filename>sandwich.txt</filename> in the repository. Harry has
just changed the file in his working copy and checked it in.
Sally updates her working copy before checking in and she gets
a conflict:</para>

<screen>
$ svn update
C sandwich.txt
Updated to revision 2.
$ ls -1
sandwich.txt
sandwich.txt.mine
sandwich.txt.r1
sandwich.txt.r2
</screen>
<!-- ###TODO What happens if the revnum is gt 99999?-->

<para>At this point, Subversion will <emphasis>not</emphasis>
allow you to commit the file <filename>sandwich.txt</filename>
until the three temporary files are removed.</para>

<screen>
$ svn commit --message "Add a few more things"
svn: Commit failed (details follow):
svn: Aborting commit: '/home/sally/svn-work/sandwich.txt' remains in conflict
</screen>

<para>If you get a conflict, you need to do one of three
things:</para>

<itemizedlist>

<listitem>
<para>Merge the conflicted text <quote>by hand</quote> (by
examining and editing the conflict markers within the
file).
</para>
</listitem>

<listitem>
<para>Copy one of the temporary files on top of your
working file.
</para>
</listitem>

<listitem>
<para>Run <command>svn revert &lt;filename&gt;</command>
to throw away all of your local changes.</para>
</listitem>

</itemizedlist>

<para>Once you've resolved the conflict, you need to let
Subversion know by running <command>svn resolved</command>.
This removes the three temporary files and Subversion no
longer considers the file to be in a state of
conflict.<footnote><para>You can always remove the temporary
files yourself, but would you really want to do that when
Subversion can do it for you? We didn't think so.</para>
</footnote></para>

<screen>
$ svn resolved sandwich.txt
Resolved conflicted state of 'sandwich.txt'
</screen>

<sect3 id="svn-ch-3-sect-4.4.1">
<title>Merging Conflicts by Hand</title>

<para>Merging conflicts by hand can be quite intimidating the
first time you attempt it, but with a little practice, it
can become as easy as falling off a bike.</para>

<para>Here's an example. Due to a miscommunication, you and
Sally, your collaborator, both edit the file
<filename>sandwich.txt</filename> at the same time. Sally
commits her changes, and when you go to update your working
copy, you get a conflict and we're going to have to edit
<filename>sandwich.txt</filename> to resolve the conflicts.
First, let's take a look at the file:</para>

<screen>
$ cat sandwich.txt
Top piece of bread
Mayonnaise
Lettuce
Tomato
Provolone
&lt;&lt;&lt;&lt;&lt;&lt;&lt; .mine
Salami
Mortadella
Prosciutto
=======
Sauerkraut
Grilled Chicken
&gt;&gt;&gt;&gt;&gt;&gt;&gt; .r2
Creole Mustard
Bottom piece of bread
</screen>

<para>The strings of less-than signs, equal signs, and
greater-than signs are conflict markers, and are not part of
the actual data in conflict. You generally want to ensure
that those are removed from the file before your next
commit. The text between the first two sets of markers is
composed of the changes you made in the conflicting
area:</para>

<screen>
&lt;&lt;&lt;&lt;&lt;&lt;&lt; .mine
Salami
Mortadella
Prosciutto
=======
</screen>

<para>The text between the second and third sets of conflict
markers is the text from Sally's commit:</para>

<screen>
=======
Sauerkraut
Grilled Chicken
&gt;&gt;&gt;&gt;&gt;&gt;&gt; .r2
</screen>

<para>Usually you won't want to just delete the conflict
markers and Sally's changes&mdash;she's going to be awfully
surprised when the sandwich arrives and it's not what she
wanted. So this is where you pick up the phone or walk
across the office and explain to Sally that you can't get
sauerkraut from an Italian deli.<footnote><para>And if you
ask them for it, they may very well ride you out of town on
a rail.</para></footnote> Once you've agreed on the changes
you will check in, edit your file and remove the conflict
markers.</para>

<screen>
Top piece of bread
Mayonnaise
Lettuce
Tomato
Provolone
Salami
Mortadella
Prosciutto
Creole Mustard
Bottom piece of bread
</screen>

<para>Now run <command>svn resolved</command>, and you're
ready to commit your changes:</para>

<screen>
$ svn resolved sandwich.txt
$ svn commit -m "Go ahead and use my sandwich, discarding Sally's edits."
</screen>

<para>Remember, if you ever get confused while editing the
conflicted file, you can always consult the three files that
Subversion creates for you in your working
copy&mdash;including your file as it was before you updated.
You can even use a third-party interactive merging tool to
examine those three files.</para>

</sect3>

<sect3 id="svn-ch-3-sect-4.4.2">
<title>Copying a File Onto Your Working File</title>

<para>If you get a conflict and decide that you want to throw
out your changes, you can merely copy one of the temporary
files created by Subversion over the file in your working
copy:</para>

<screen>
$ svn update
C sandwich.txt
Updated to revision 2.
$ ls sandwich.*
sandwich.txt sandwich.txt.mine sandwich.txt.r2 sandwich.txt.r1
$ cp sandwich.txt.r2 sandwich.txt
$ svn resolved sandwich.txt
</screen>

</sect3>

<sect3 id="svn-ch-3-sect-4.4.3">
<title>Punting: Using <command>svn revert</command></title>

<para>If you get a conflict, and upon examination decide that
you want to throw out your changes and start your edits again,
just revert your changes:</para>

<screen>
$ svn revert sandwich.txt
Reverted 'sandwich.txt'
$ ls sandwich.*
sandwich.txt
</screen>

<para>Note that when you revert a conflicted file, you don't
have to run <command>svn resolved</command>.</para>

</sect3>

<para>Now you're ready to check in your changes. Note that
<command>svn resolved</command>, unlike most of the other
commands we've dealt with in this chapter, requires an
argument. In any case, you want to be careful and only run
<command>svn resolved</command> when you're certain that you've
fixed the conflict in your file&mdash;once the temporary files
are removed, Subversion will let you commit the file even if
it still contains conflict markers.</para>

</sect2>

<sect2 id="svn-ch-3-sect-4.5">
<title>Commit Your Changes</title>

<para>Finally! Your edits are finished, you've merged all
changes from the server, and you're ready to commit your
changes to the repository.</para>

<para>The <command>svn commit</command> command sends all of
your changes to the repository. When you commit a change,
you need to supply a <firstterm>log message</firstterm>,
describing your change. Your log message will be attached
to the new revision you create. If your log message is
brief, you may wish to supply it on the command line using
the <option>--message</option> (or
<option>-m</option>) option:</para>

<screen>
$ svn commit --message "Corrected number of cheese slices."
Sending sandwich.txt
Transmitting file data .
Committed revision 3.
</screen>

<para>However, if you've been composing your log message as you
work, you may want to tell Subversion to get the message from
a file by passing the filename with the
<option>--file</option> switch:</para>

<screen>
$ svn commit --file logmsg
Sending sandwich
Transmitting file data .
Committed revision 4.
</screen>

<para>If you fail to specify either the
<option>--message</option> or <option>--file</option> switch,
then Subversion will automatically launch your favorite editor
(as defined in the environment variable
<literal>$EDITOR</literal>) for composing a log
message.</para>


<tip>
<para>If you're in your editor writing a commit message and
decide that you want to cancel your commit, you can just
quit your editor without saving changes. If you've already
saved your commit message, simply delete the text and save
again.</para>

<screen>
$ svn commit
Waiting for Emacs...Done

Log message unchanged or not specified
a)bort, c)ontinue, e)dit
a
$
</screen>
</tip>

<para>The repository doesn't know or care if your changes make
any sense as a whole; it only checks to make sure that nobody
else has changed any of the same files that you did when you
weren't looking. If somebody <emphasis>has</emphasis> done
that, the entire commit will fail with a message informing you
that one or more of your files is out-of-date:</para>

<screen>
$ svn commit --message "Add another rule"
Sending rules.txt
svn: Commit failed (details follow):
svn: Out of date: 'rules.txt' in transaction 'g'
</screen>

<para>At this point, you need to run <command>svn
update</command>, deal with any merges or conflicts that
result, and attempt your commit again.</para>


<para>That covers the basic work cycle for using Subversion.
There are many other features in Subversion that you can use
to manage your repository and working copy, but you can get by
quite easily using only the commands that we've discussed so
far in this chapter.</para>

</sect2>

</sect1>

<!-- ================================================================= -->
<!-- ======================== SECTION 6 ============================== -->
<!-- ================================================================= -->
<sect1 id="svn-ch-3-sect-6">
<title>Examining History</title>

<para>As we mentioned earlier, the repository is like a time
machine. It keeps a record of every change ever committed,
and allows you to explore this history by examining previous
versions of files and directories as well as the metadata that
accompanies them. With a single Subversion command, you can
check out the repository (or restore an existing working copy)
exactly as it was at any date or revision number in the past.
However, sometimes you just want to <emphasis>peer
into</emphasis> the past instead of <emphasis>going
into</emphasis> the past.</para>

<para>There are several commands that can provide you with
historical data from the repository:</para>

<variablelist>

<varlistentry>
<term><command>svn log </command></term>
<listitem>
<para>Shows you broad information: log messages attached
to revisions, and which paths changed in each
revision.</para>
</listitem>
</varlistentry>

<varlistentry>
<term><command>svn diff </command></term>
<listitem>
<para>Shows you the specific details of how a file changed
over time.</para>
</listitem>
</varlistentry>

<varlistentry>
<term><command>svn cat </command></term>
<listitem>
<para>This is used to retrieve any file as it existed in a
particular revision number and display it on your
screen.</para>
</listitem>
</varlistentry>

<varlistentry>
<term><command>svn list </command></term>
<listitem>
<para>Displays the files in a directory for any given
revision.</para>
</listitem>
</varlistentry>

</variablelist>


<sect2 id="svn-ch-3-sect-5.1">
<title><command>svn log</command></title>

<para>To find out information about the history of a file or
directory, use the <command>svn log</command>
command. <command>svn log</command> will provide you with a
record of who made changes to a file or directory, at what
revision it changed, the time and date of that revision, and,
if it was provided, the log message that accompanied the
commit.</para>

<screen>
$ svn log
------------------------------------------------------------------------
r3 | sally | Mon, 15 Jul 2002 18:03:46 -0500 | 1 line

Added include lines and corrected # of cheese slices.
------------------------------------------------------------------------
r2 | harry | Mon, 15 Jul 2002 17:47:57 -0500 | 1 line

Added main() methods.
------------------------------------------------------------------------
r1 | sally | Mon, 15 Jul 2002 17:40:08 -0500 | 1 line

Initial import
------------------------------------------------------------------------
</screen>

<para>Note that the log messages are printed in
<emphasis>reverse chronological order</emphasis> by default.
If you wish to see a different range of revisions in a
particular order, or just a single revision, pass the
<option>--revision</option> (<option>-r</option>)
switch:</para>

<screen>
$ svn log --revision 5:19 # shows logs 5 through 19 in chronological order

$ svn log -r 19:5 # shows logs 5 through 19 in reverse order

$ svn log -r 8 # shows log for revision 8
</screen>

<para>You can also examine the log history of a single file or directory.
For example:</para>

<screen>
$ svn log foo.c
&hellip;
$ svn log http://foo.com/svn/trunk/code/foo.c
&hellip;
</screen>

<para>These will display log messages <emphasis>only</emphasis>
for those revisions in which the working file (or URL)
changed.</para>

<para>If you want even more information about a file or
directory, <command>svn log</command> also takes a
<option>--verbose</option> (<option>-v</option>) switch.
Because Subversion allows you to move and copy files and
directories, it is important to be able to track path changes
in the filesystem, so in verbose mode, <command>svn
log</command> will include a list of changed paths in a
revision in its output:</para>

<screen>
$ svn log -r 8 -v
------------------------------------------------------------------------
r8 | sally | 2002-07-14 08:15:29 -0500 | 1 line
Changed paths:
M /trunk/code/foo.c
M /trunk/code/bar.h
A /trunk/code/doc/README

Frozzled the sub-space winch.

------------------------------------------------------------------------
</screen>

<sidebar>
<title>Why Does <command>svn log</command> Give Me an Empty
Response?</title>

<para>After working with Subversion for a bit, most users will
come across something like this:</para>

<screen>
$ svn log -r 2
------------------------------------------------------------------------
$
</screen>

<para>At first glance, this seems like an error. But recall
that while revisions are repository-wide, <command>svn
log</command> operates on a path in the repository. If you
supply no path, Subversion uses the current working
directory as the default target. As a result, if you're
operating in a subdirectory of your working copy and attempt
to log a revision in which neither that directory nor any of
its children was changed, Subversion will give you an empty
log. If you want to see what changed in that revision, try
pointing <command>svn log</command> directly at the top-most
URL of your repository, as in <command>svn log -r 2
http://svn.collab.net/repos/svn</command>.</para>

</sidebar>

</sect2>

<sect2 id="svn-ch-3-sect-5.2">
<title>svn diff</title>

<para>We've already seen <command>svn diff</command>
before&mdash;it displays file differences in unified diff
format; it was used to show the local modifications made to
our working copy before committing to the repository.</para>

<para>In fact, it turns out that there are
<emphasis>three</emphasis> distinct uses of <command>svn
diff</command>:</para>

<itemizedlist>

<listitem>
<para>Examine local changes</para>
</listitem>

<listitem>
<para>Compare your working copy to the repository</para>
</listitem>

<listitem>
<para>Compare repository to repository</para>
</listitem>

</itemizedlist>

<sect3 id="svn-ch-3-sect-5.2.1">
<title>Examining Local Changes</title>

<para>As we've seen, invoking <command>svn diff</command> with
no switches will compare your working files to the cached
<quote>pristine</quote> copies in
the <filename>.svn</filename> area:</para>

<screen>
$ svn diff
Index: rules.txt
===================================================================
--- rules.txt (revision 3)
+++ rules.txt (working copy)
@@ -1,4 +1,5 @@
Be kind to others
Freedom = Responsibility
Everything in moderation
-Chew with your mouth open
+Chew with your mouth closed
+Listen when others are speaking
$
</screen>

</sect3>

<sect3 id="svn-ch-3-sect-5.2.2">
<title>Comparing Working Copy to Repository</title>

<para>If a single <option>--revision</option>
(<option>-r</option>) number is passed, then your
working copy is compared to the specified revision in the
repository.</para>

<screen>
$ svn diff --revision 3 rules.txt
Index: rules.txt
===================================================================
--- rules.txt (revision 3)
+++ rules.txt (working copy)
@@ -1,4 +1,5 @@
Be kind to others
Freedom = Responsibility
Everything in moderation
-Chew with your mouth open
+Chew with your mouth closed
+Listen when others are speaking
$
</screen>

</sect3>

<sect3 id="svn-ch-3-sect-5.2.3">
<title>Comparing Repository to Repository</title>

<para>If two revision numbers, separated by a colon, are
passed via <option>--revision</option>
(<option>-r</option>), then the two revisions are directly
compared.</para>

<screen>
$ svn diff --revision 2:3 rules.txt
Index: rules.txt
===================================================================
--- rules.txt (revision 2)
+++ rules.txt (revision 3)
@@ -1,4 +1,4 @@
Be kind to others
-Freedom = Chocolate Ice Cream
+Freedom = Responsibility
Everything in moderation
Chew with your mouth closed
$
</screen>

<para>Not only can you use <command>svn diff</command> to
compare files in your working copy to the repository, but
if you supply a URL argument, you can examine the
differences between items in the repository without even
having a working copy. This is especially useful if you
wish to inspect changes in a file when you don't have a
working copy on your local machine:</para>

<screen>
$ svn diff --revision 4:5 http://svn.red-bean.com/repos/example/trunk/text/rules.txt
&hellip;
$
</screen>

</sect3>

</sect2>

<sect2 id="svn-ch-3-sect-5.3">
<title><command>svn cat</command></title>

<para>If you want to examine an earlier version of a file and
not necessarily the differences between two files, you can use
<command>svn cat</command>:</para>

<screen>
$ svn cat --revision 2 rules.txt
Be kind to others
Freedom = Chocolate Ice Cream
Everything in moderation
Chew with your mouth closed
$
</screen>

<para>You can also redirect the output directly into a
file:</para>

<screen>
$ svn cat --revision 2 rules.txt &gt; rules.txt.v2
$
</screen>

<para>You're probably wondering why we don't just use
<command>svn update --revision</command> to update the file to
the older revision. There are a few reasons why we might
prefer to use <command>svn cat</command>.</para>

<para>First, you may want to see the differences between two
revisions of a file using an external diff program (perhaps a
graphical one, or perhaps your file is in such a format that
the output of unified diff is nonsensical). In this case,
you'll need to grab a copy of the old revision, redirect it to
a file, and pass both that and the file in your working copy
to your external diff program.</para>

<para>Sometimes it's easier to look at an older version of a
file in its entirety as opposed to just the differences
between it and another revision.</para>

</sect2>

<sect2 id="svn-ch-3-sect-5.4">
<title><command>svn list</command></title>

<para>The <command>svn list</command> command shows you what
files are in a repository directory without actually
downloading the files to your local machine:</para>

<screen>
$ svn list http://svn.collab.net/repos/svn
README
branches/
clients/
tags/
trunk/
</screen>

<para>If you want a more detailed listing, pass the
<option>--verbose</option> (<option>-v</option>) flag to get
output like this.</para>

<screen>
$ svn list --verbose http://svn.collab.net/repos/svn
2755 harry 1331 Jul 28 02:07 README
2773 sally Jul 29 15:07 branches/
2769 sally Jul 29 12:07 clients/
2698 harry Jul 24 18:07 tags/
2785 sally Jul 29 19:07 trunk/
</screen>

<para>The columns tell you the revision at which the file or
directory was last modified, the user who modified it, the size
if it is a file, the date it was last modified, and the item's
name.</para>

</sect2>

<sect2 id="svn-ch-3-sect-5.5">
<title>A Final Word on History</title>

<para>In addition to all of the above commands, you can use
<command>svn update</command> and <command>svn
checkout</command> with the <option>--revision</option> switch
to take an entire working copy <quote>back in time</quote>
<footnote><para>See? We told you that Subversion was a time
machine.</para></footnote>:</para>

<screen>
$ svn checkout --revision 1729 # Checks out a new working copy at r1729
&hellip;
$ svn update --revision 1729 # Updates an existing working copy to r1729
&hellip;
</screen>

</sect2>

</sect1>


<!-- ================================================================= -->
<!-- ======================== SECTION 7 ============================== -->
<!-- ================================================================= -->
<sect1 id="svn-ch-3-sect-7">
<title>Other Useful Commands</title>

<para>While not as frequently used as the commands previously
discussed in this chapter, you will occasionally need these
commands.</para>

<sect2 id="svn-ch-3-sect-7.1">
<title><command>svn cleanup</command></title>

<para>When Subversion modifies your working copy (or any
information within <filename>.svn</filename>), it tries to do
so as safely as possible. Before changing anything, it writes
its intentions to a log file, executes the commands in the log
file, then removes the log file (this is similar in design to
a journaled filesystem). If a Subversion operation is
interrupted (if the process is killed, or if the machine
crashes, for example), the log files remain on disk. By
re-executing the log files, Subversion can complete the
previously started operation, and your working copy can get
itself back into a consistent state.</para>

<para>And this is exactly what <command>svn cleanup</command>
does: it searches your working copy and runs any leftover
logs, removing locks in the process. If Subversion ever tells
you that some part of your working copy is
<quote>locked</quote>, then this is the command that you
should run. Also, <command>svn status</command> will display
an <literal>L</literal> next to locked items:</para>

<screen>
$ svn status
L somedir
M somedir/foo.c

$ svn cleanup
$ svn status
M somedir/foo.c
</screen>

</sect2>


<sect2 id="svn-ch-3-sect-7.3">
<title><command>svn import</command></title>

<para>The <command>svn import</command> command is a quick way
to copy an unversioned tree of files into a repository,
creating intermediate directories as necessary.</para>

<screen>
$ svnadmin create /usr/local/svn/newrepos
$ svn import mytree file:///usr/local/svn/newrepos/some/project
Adding mytree/foo.c
Adding mytree/bar.c
Adding mytree/subdir
Adding mytree/subdir/quux.h

Committed revision 1.
</screen>

<para>The previous example copied the contents of directory
<filename>mytree</filename> under the directory
<filename>some/project</filename> in the repository:</para>

<screen>
$ svn ls file:///usr/local/svn/newrepos/some/project
bar.c
foo.c
subdir/
</screen>

<para>Note that after the import is finished, the original tree
is <emphasis>not</emphasis> converted into a working copy. To
start working, you still need to <command>svn
checkout</command> a fresh working copy of the tree.</para>

</sect2>

</sect1>

<!-- ================================================================= -->
<!-- ======================== SECTION 8 ============================== -->
<!-- ================================================================= -->
<sect1 id="svn-ch-3-sect-8">
<title>Summary</title>

<para>Now we've covered most of the Subversion client
commands. Notable exceptions are those dealing with
branching and merging (see <xref linkend="svn-ch-4"/>) and
properties (see <xref linkend="svn-ch-7-sect-2"/>).
However, you may want to take a moment to skim through <xref
linkend="svn-ch-9"/> to get an idea of all the many
different commands that Subversion has&mdash;and how you can
use them to make your work easier.</para>

</sect1>

</chapter>

<!--
local variables:
sgml-parent-document: ("book.xml" "chapter")
end:
-->
Show details Hide details

Change log

r1122 by cmpilato on Feb 25, 2005   Diff
Rename tag to associate with English
version only.
Go to: 

Older revisions

r1107 by sussman on Feb 23, 2005   Diff
Create 'book-1.0-final' tag.  This is
a snapshot of the last version
of the book's trunk before we started
documenting 1.1 features.

r644 by maxb on Aug 28, 2004   Diff
Act on comments in issue 1568.

* doc/book/book/ch03.xml (svn-
ch-3-sect-4.1): Rephrase the
decription of
...
r643 by mthelen on Aug 25, 2004   Diff
Fix a typo.  Thanks to
<rengmann@lycos.de> for noticing it.

* doc/book/book/ch03.xml
  (svn-ch-3-sect-5.2.1): Fix a typo.
All revisions of this file

File info

Size: 82723 bytes, 2139 lines

File properties

svn:mime-type
text/xml
svn:eol-style
native
Hosted by Google Code