SVK 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 SVK in the course of a day's work.
The typical work cycle looks like this:
Update your working copy
svk sync
svk update
Make changes
svk add
svk delete
svk copy
svk move
Examine your changes
svk status
svk diff
svk revert
Merge others' changes into your working copy
svk update
svk resolved
Commit your changes
svk commit
When working on a project with a team, you'll want to update your mirror to receive any changes made by other developers on the project since your last update.
$ svk sync //mirror/project Retrieving log information from 500 to 502 Committed revision 503 from revision 500. Committed revision 504 from revision 501. Committed revision 505 from revision 502.
Then you'll want to bring those changes into your working copy. Use svk update to bring your working copy into sync with the latest revision in your depot.
$ svk update Syncing //mirror/project/trunk(/mirror/project/trunk) in /Users/sally/project to 505. U foo.c U bar.c
You can combine the first 2 steps by passing the
--sync (-s) switch to
svk update
In this case, someone else checked in modifications to
both foo.c and bar.c
since the last time you updated, and SVK has updated
your working copy to include those changes.
Let's examine the output of svk update 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 SVK performed to bring your working copy up-to-date:
U fooFile foo was
Updated (received changes
from the server).
A fooFile or directory foo was
Added to your working
copy.
D fooFile or directory foo was
Deleted from your working
copy.
R fooFile or directory foo was
Replaced in your working
copy; that is, foo was deleted, and a
new item with the same name was added. While they may have
the same name, the depot considers them to be distinct
objects with distinct histories.
G fooFile foo received new changes
from the depot, but your working copy version of the
file had your modifications. The changes did not
intersect, so SVK has successfully
merGed the depot's
changes into the file without a problem.
g fooFile foo received new changes
from the depot, but your working copy version of the
file had your modifications. However the changes were
exactly the same as your local modifications, so SVK has
successfully merged the
depot's changes into the file without changing a
thing.
C fooFile foo received
Conflicting 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.
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 SVK commands that you will use here are svk add, svk delete, svk copy, and svk move. However, if you are merely editing files that are already in SVK, you may not need to use any of these commands until you commit. Changes you can make to your working copy:
This is the simplest sort of change. You don't need to tell SVK that you intend to change a file; just make your changes. SVK will be able to automatically detect which files have been changed.
You can ask SVK to “mark” 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 depot until you commit them.
To make file changes, use your text editor, word processor, graphics program, or whatever tool you would normally use. SVK handles binary files just as easily as it handles text files—and just as efficiently too.
Here is an overview of the four SVK subcommands that you'll use most often to make tree changes (we'll cover svk import and svk mkdir later).
While you can edit your files with whatever tool you like, you shouldn't change the structure of your working copy without letting SVK know what you're doing. Use the svk copy, svk delete, and svk move commands to change the structure of your working copy, and use the svk add command to place new files and directories under version control.
Schedule file, directory, or symbolic link
foo to be added to the depot.
When you next commit, foo will
become a child of its parent directory. Note that if
foo is a directory, everything
underneath foo will be scheduled
for addition. If you only want to add
foo itself, pass the
--non-recursive (-N)
switch.
Schedule file, directory, or symbolic link
foo to be deleted from the
depot. If foo is a file or
link, it is immediately deleted from your working copy.
If foo is a directory, it is not
deleted, but SVK schedules it for deletion. When
you commit your changes, foo will
be removed from your working copy and the depot.
[8]
Create a new item bar as a
duplicate of foo.
bar is automatically scheduled for
addition. When bar is added to the
depot on the next commit, its copy history is
recorded (as having originally come from
foo). svk copy
does not create intermediate directories unless you pass
it the --parent switch.
This command is exactly the same as running
svk copy foo bar; svk delete foo.
That is, bar is scheduled for
addition as a copy of foo, and
foo is scheduled for removal.
svk move does not create intermediate
directories unless you pass it the
--parent switch.
Once you've finished making changes, you need to commit them to the depot, 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 svk status, svk diff, and svk revert. 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.
You'll probably use the svk status command more than any other SVK command.
If you run svk status at the top of
your working copy with no arguments, it will detect all file
and tree changes you've made. Below are examples of
the different status codes that svk
status can return. (Note that the text following
# is not
actually printed by svk status.)
M bar.c # the content in bar.c has local modifications M baz.c # baz.c has property but no content modifications ? foo.o # svk doesn't manage foo.o ! some_dir # svk manages this, but it's missing or incomplete ~ qux # versioned as file/dir/link, but type has changed I .screenrc # svk doesn't manage this, and is set to ignore it 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 # file is scheduled for deletion A stuff/loot/bloo.h # file is scheduled for addition C stuff/loot/lump.c # file has textual conflicts from an update C stuff/loot/glub.c # file has property conflicts from an update R xyz.c # file is scheduled for replacement
In this output format svk status prints three columns of characters, followed by a whitespace character, 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:
A itemThe file, directory, or symbolic link
item has been scheduled for
addition into the depot.
C itemThe file item 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
depot.
D itemThe file, directory, or symbolic link
item has been scheduled for
deletion from the depot.
M itemThe contents of the file item
have been modified.
R itemThe file, directory, or symbolic link
item has been scheduled to
replace item in the depot.
This means that the object is first deleted, then
another object of the same name is added, all within a
single revision.
? itemThe file, directory, or symbolic link
item is not under version
control. You can silence the question marks by either
passing the --quiet
(-q) switch to svk
status, or by setting the
svn:ignore property on the parent
directory. For more information on ignored files, see
the section called “”.
! itemThe file, directory, or symbolic link
item is under version control but
is missing or somehow incomplete. The item can be
missing if it's removed using a non-SVK command. In
the case of a directory, it can be incomplete if you
happened to interrupt a checkout or update. A quick
svk revert --recursive item
will refetch the directory from the depot, or
svk revert item will restore a
missing file.
~ itemThe file, directory, or symbolic link
item is in the depot as one
kind of object, but what's actually in your working
copy is some other kind. For example, SVK
might have a file in the depot, but you removed
the file and created a directory in its place, without
using the svk delete or
svk add command.
I itemThe file, directory, or symbolic link
item is not under version control,
and SVK is configured to ignore it during
svk add, svk import
and svk status operations. For more
information on ignored files, see the section called “”. Note that this
symbol only shows up if you pass the
--no-ignore switch to svk
status—otherwise the file would be
ignored and not listed at all!
The second column tells the status of a file or
directory's properties (see the section called “” for more information on
properties). If an M
appears in the second column, then the properties have been
modified, otherwise a whitespace will be printed.
The third column will only show whitespace or a
+ which means that the file
or directory is scheduled to be added or modified with
additional attached history. This typically happens when you
svk move or svk copy a file
or directory. If you see
A +, this means
the item is scheduled for addition-with-history. It could be
a file, or the root of a copied directory.
+
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.
M + means the item
is part of a subtree scheduled for addition-with-history,
and 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.
If you pass a specific path to svk status, it gives you information about that item alone:
$ svk status stuff/fish.c D stuff/fish.c
svk status also has a
--verbose (-v) switch,
which will show you the status of every
item in your working copy, even if it has not been
changed:
$ svk 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
This is the “long form” output of svk status. 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.
None of the above invocations to svk
status show you changes in the depot that your
working copy does not yet have. To do this you need to use
the svk update with the
--check-only (-C) switch,
which will show what would happen if you actually ran
svk update:
$ svk update --check-only Syncing //mirror/fish/trunk(/mirror/fish/trunk) in /Users/sally/svk to 35. C README U stuff/trout.c 1 conflict found.
Notice the two entries.
svk update at this point, you would
receive changes to README
and trout.c. This tells you some very
useful information—you'll need to update and get the
server changes on README before you
commit, or the depot will reject your commit for being
out-of-date. (More on this subject later.)
Another way to examine your changes is with the svk diff command. You can find out exactly how you've modified things by running svk diff with no arguments, which prints out file changes in unified diff format:[9]
$ svk diff
=== bar.c
==================================================================
--- bar.c (revision 3)
+++ bar.c (local)
@@ -1,7 +1,12 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <stdio.h>
int main(void) {
- printf("Sixty-four slices of American Cheese...\n");
+ printf("Sixty-five slices of American Cheese...\n");
return 0;
}
=== README
==================================================================
--- README (revision 3)
+++ README (local)
@@ -193,3 +193,4 @@
+Note to self: pick up laundry.
=== stuff/fish.c
==================================================================
--- stuff/fish.c (revision 1)
+++ stuff/fish.c (local)
-Welcome to the file known as 'fish'.
-Information on fish will be here soon.
=== stuff/things/bloo.h
==================================================================
--- stuff/things/bloo.h (revision 8)
+++ stuff/things/bloo.h (local)
+Here is a new file to describe
+things about bloo.
The svk diff command produces this
output by comparing your working files against the
BASE revision in the depot. Files
scheduled for addition are displayed as all added-text, and
files scheduled for deletion are displayed as all deleted
text.
Output is displayed in unified diff
format. That is, removed lines are prefaced
with a - and added lines are prefaced
with a +. svk diff
also prints filename and offset information useful to the
patch program, so you can generate
“patches” by redirecting the diff output to a
file:
$ svk diff > patchfile
You could, for example, email the patch file to another developer for review or testing prior to commit.
However SVK has a much better way to create patches,
which is by using the --patch switch to
svk commit or almost any other command
that modifies the depot. Some notable advantages of this
method over using svk diff include that
patches contain log messages, and tree changes, as well as
binary file changes, while remaining safe to be sent
though email.
$ svk commit --message '' --patch - > patchfile
Now suppose you see the above diff output, and realize
that your changes to README are a
mistake; perhaps you accidentally typed that text into the
wrong file in your editor.
This is a perfect opportunity to use svk revert.
$ svk revert README Reverted README
SVK reverts the file to its pre-modified state by overwriting it with the version your working copy was based on. But also note that svk revert can undo any scheduled operations—for example, you might decide that you don't want to add a new file after all:
$ svk status foo ? foo $ svk add foo A foo $ svk revert foo Reverted foo $ svk status foo ? foo
Or perhaps you mistakenly removed a file from version control:
$ svk status README $ svk delete README D README $ svk revert README Reverted README $ svk status README
We've already seen how svk update --check-only can predict conflicts. Suppose you run svk update and some interesting things occur:
$ svk update Syncing //mirror/fish/trunk(/mirror/fish/trunk) in /Users/sally/svk to 46. U INSTALL G README g foo.c
The U,
G and
g codes are no cause for
concern; those files cleanly absorbed changes from the
depot. The files marked with
U contained no local changes
but were Updated with changes
from the repository. The G
stands for merGed, which
means that the file had local changes to begin with, but the
changes coming from the depot didn't overlap with the local
changes. Finally the g
stands for merged, but in
this case your local copy already contained all the changes
from the depot, so the update operation did not modify the
file.
When a file has local changes, and the changes coming from the depot overlap with the local changes, that file is considered to have a conflict. When this happens SVK gives you a number of choices:
$ svk update Syncing //mirror/fish/trunk(/mirror/fish/trunk) in /Users/sally/svk to 47. Conflict found in bar.c: e)dit, d)iff, m)erge, s)kip, t)heirs, y)ours, h)elp? [e]
At this point you have a number of options.
If SVK doesn't consider the file to be of a mergeable type
then only the t and y
options below are available. (SVK uses the
svn:mime-type property to decide if a
file is capable of contextual, line-based merging. See
the section called “” to
learn more.)
e—editAfter SVK places conflict markers—special strings of text which delimit the “sides” of the conflict—into the file to visibly demonstrate the overlapping areas, the file is opened in an editor window.
If after editing the file all the conflict markers
have been removed SVK will now give you the option to
accept (a) the changes you have made.
All the other options remain available as well, so you
can now view the diffs after your edits, re-edit the
file, etc.
d—diffDiff your file against the merged file.
This runs the internal diff tool or that specified by the
$SVKDIFF environment variable.
dm—diff mergedDiff the base revision of the file against
the merged file.
This runs the internal diff tool or that specified by the
$SVKDIFF environment variable.
dt—diff theirsDiff the base revision of the file against
the revision of the file from the depot.
This runs the internal diff tool or that specified by the
$SVKDIFF environment variable.
dy—diff yoursDiff the base revision of the file against
the local version of the file (or when merging directly to
a depot against revision of the file being merged to).
This runs the internal diff tool or that specified by the
$SVKDIFF environment variable.
m—mergeInvokes a 3 way merging tool or your choice and lets you resolve the conflicts using that. If you have more than one supported merging tool installed SVK will prompt you to pick one like so:
e)dit, d)iff, m)erge, s)kip, t)heirs, y)ours, h)elp? [a] m Multiple merge tools found, choose one: (to skip this question, set the SVKMERGE environment variable to one of them) 1)FileMerge, 2)Vim, q)uit? 2
The merge tools listed will vary based on which ones
you have installed. Like the message says you can set
your $SVKMERGE environment variable
to avoid having to choose a merge tool each time you
select the merge (m) option.
Currently SVK supports the following merge tools:
AraxisMerge, Emacs, FileMerge, GVim, GtkDiff, Guiffy,
KDiff3, Meld, P4WinMerge, TkDiff, TortoiseMerge, Vim,
XXDiff.
Entering q will return you to the
previous menu and let you choose any of the other
options again.
This option is very similar to the edit
(e) option in that, after merging the
file SVK will give you the option to accept
(a) the changes you have made. All
the other options remain available as well, so you can
now view the diffs after your edits, edit the file,
re-merge it, etc.
s[10]—skipSVK places conflict markers—special strings of text which delimit the “sides” of the conflict—into the file to visibly demonstrate the overlapping areas.
The file in question remains in conflict and running
svk status on it will show it as
being in state C or
conflicting. You will need to manually edit the file to
remove the conflicts, and run svk
resolved once you have done so to let SVK know
the file is no longer in conflict.
t—theirsKeep the changes between the base and depot version of the file. This discards the local changes you made to the file (or when merging directly to a depot, discards the changes between the merge base and the revision of the file being merged to).
y—yoursKeep the local version of the file (or when merging directly to a depot keep the revision of the file being merged to). This discards the changes made between the base and the depot version of the file.
h—helpDisplays help explaining all the different options presented.
For example, Sally makes changes to the file
sandwich.txt in the depot. 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. She decides to skip doing the merge and do it by
hand after the fact:
$ svk update Syncing //bread/trunk(/bread/trunk) in /Users/sally/bread to 70. Conflict found in sandwich.txt: e)dit, d)iff, m)erge, s)kip, t)heirs, y)ours, h)elp? [e] s C sandwich.txt 1 conflict found.
At this point, SVK will not
allow you to commit the file sandwich.txt
until the conflict has been resolved.
$ svk commit --message "Add a few more things" 1 conflict detected. Use 'svk resolved' after resolving them.
If you get a conflict, you need to do one of three things:
Merge the conflicted text “by hand” (by examining and editing the conflict markers within the file).
Run svk revert <filename> to throw away all of your local changes.
Once you've resolved the conflict, you need to let SVK know by running svk resolved. After this SVK no longer considers the file to be in a state of conflict.
$ svk resolved sandwich.txt /Users/sally/bread/sandwich.txt marked as resolved.
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.
Here's an example. Due to a miscommunication, you and
Sally, your collaborator, both edit the file
sandwich.txt 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
sandwich.txt to resolve the conflicts.
First, let's take a look at the file:
$ cat sandwich.txt Top piece of bread Mayonnaise Lettuce Tomato >>>> YOUR VERSION sandwich.txt 112646405792039 Salami Mortadella Prosciutto Djon Mustard ==== ORIGINAL VERSION sandwich.txt 112646405792039 Provolone Creole Mustard ==== THEIR VERSION sandwich.txt 112646405792039 Provolone Sauerkraut Grilled Chicken Creole Mustard <<<< 112646405792039 Bottom piece of bread
The lines ending in 112646405792039[11] 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:
>>>> YOUR VERSION sandwich.txt 112646405792039 Salami Mortadella Prosciutto Djon Mustard ==== ORIGINAL VERSION sandwich.txt 112646405792039
The text between the second and third sets of conflict markers (if any) is the text from the original revision of the file that both your working copy and Sally's version were based on:
==== ORIGINAL VERSION sandwich.txt 112646405792039 Provolone Creole Mustard ==== THEIR VERSION sandwich.txt 112646405792039
The text between the third and fourth sets of conflict markers is the text from Sally's commit:
==== THEIR VERSION sandwich.txt 112646405792039 Provolone Sauerkraut Grilled Chicken Creole Mustard <<<< 112646405792039
Usually you won't want to just delete the conflict markers and Sally's changes—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.[12] Once you've agreed on the changes you will check in, edit your file and remove the conflict markers.
Top piece of bread Mayonnaise Lettuce Tomato Provolone Salami Mortadella Prosciutto Grilled Chicken Djon Mustard Bottom piece of bread
Now run svk resolved, and you're ready to commit your changes:
$ svk resolved sandwich.txt $ svk commit -m "Go ahead and use my sandwich, discarding Sally's Sauerkraut."
If you get a conflict and you want to resolve it right
away you can choose the edit option to
edit the file in conflict. SVK will launch your selected
editor with a buffer containing the exact same contents you
would have gotten if you used the skip
option above. Once you finish editing the file and all the
conflict markers have been removed SVK will allow you to
accept the changes you made:
$ svk update Syncing //bread/trunk(/bread/trunk) in /Users/sally/bread to 70. Conflict found in sandwich.txt: e)dit, d)iff, m)erge, s)kip, t)heirs, y)ours, h)elp? [e] e Waiting for editor... Merged sandwich.txt: a)ccept, e)dit, d)iff, m)erge, s)kip, t)heirs, y)ours, h)elp? [a] a G sandwich.txt
If you get a conflict and decide that you want to throw
out your changes, you can merely select the
theirs option when ask to resolve the
conflict:
$ svk update Syncing //bread/trunk(/bread/trunk) in /Users/sally/bread to 70. Conflict found in sandwich.txt: e)dit, d)iff, m)erge, s)kip, t)heirs, y)ours, h)elp? [e] t G sandwich.txt
If you get a conflict and decide that you want to discard
the changes someone else has made to a file you have
modified, you can merely select the
yours option when ask to resolve the
conflict:
$ svk update Syncing //bread/trunk(/bread/trunk) in /Users/sally/bread to 70. Conflict found in sandwich.txt: e)dit, d)iff, m)erge, s)kip, t)heirs, y)ours, h)elp? [e] y G sandwich.txt
It's rare that you would do this blindly (since you
don't know what the changes are that you are discarding) so
in most cases you'd want to look at the changes first. To
do so you would use dt to show their
changes:
$ svk update Syncing //bread/trunk(/bread/trunk) in /Users/sally/bread to 70. Conflict found in sandwich.txt: e)dit, d)iff, m)erge, s)kip, t)heirs, y)ours, h)elp? [e] dt --- sandwich.txt (BASE) +++ sandwich.txt (THEIRS) @@ -3,5 +3,7 @@ Lettuce Tomato Provolone +Sauerkraut +Grilled Chicken Creole Mustard Bottom piece of bread Conflict found in sandwich.txt: e)dit, d)iff, m)erge, s)kip, t)heirs, y)ours, h)elp? [e] y G sandwich.txt
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:
$ svk revert sandwich.txt Reverted 'sandwich.txt'
Note that when you revert a conflicted file, you don't have to run svk resolved.
Now you're ready to check in your changes. Note that svk resolved, 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 svk resolved when you're certain that you've fixed the conflict in your file—once you have run svk resolved, SVK will let you commit the file even if it still contains conflict markers.
Finally! Your edits are finished, you've merged all changes from the server, and you're ready to commit your changes to the depot.
The svk commit command sends all of
your changes to the depot. When you commit a change, you
need to supply a log message,
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
--message (or -m)
switch:
$ svk commit --message "Corrected number of cheese slices." Committed revision 71.
However, if you've been composing your log message as you
work, you may want to tell SVK to get the message from
a file by passing the filename with the
--file switch:
$ svk commit --file logmsg Committed revision 71.
If you fail to specify either the
--message or --file switch,
then SVK will automatically launch your favorite editor (see
the $SVN_EDITOR section in the section called “”) for composing a
log message.
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.
$ svk commit Waiting for editor... Log message not modified: a)bort, e)dit, c)ommit?a Aborted. $
The depot 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 has done that, the entire commit will fail with a message informing you that one or more of your files is out-of-date:
$ svk commit --message "Add more cheese" Transaction is out of date: Out of date: '/bread/trunk/sandwich.txt' in transaction '71-1' Please update checkout first.
At this point, you need to run svk update, deal with any merges or conflicts that result, and attempt your commit again.
That covers the basic work cycle for using SVK. There are many other features in SVK 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.
[8] Of course, nothing is ever totally
deleted from the depot—just from the
HEAD of the depot. 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.
[9] SVK 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 with any options you wish to pass to it by setting
the $SVKDIFF environment variable. For
example, to see local differences in file
foo.c in context output format while
ignoring whitespace changes, you might run
SVKDIFF="diff -bc" svk diff foo.c.
[10] This option is not available when merging directly to a depot
[11] This number is generated at by SVK for each conflict.
[12] And if you ask them for it, they may very well ride you out of town on a rail.