3.5 Basic Work Cycle

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 run through the most common things that you might find yourself doing with Subversion in the course of a day's work.

The typical work cycle looks like this:

  • Update your working copy

    • svn update

  • Make changes

    • svn add

    • svn delete

    • svn copy

    • svn move

  • Examine your changes

    • svn status

    • svn diff

    • svn revert

  • Merge others' changes

    • svn merge

    • svn resolved

    • Commit your changes

    • svn commit

3.5.1 Update Your Working Copy

When working on a project with a team, you may want to update your working copy to receive any changes made since your last update by other developers on the project. Use svn update to bring your working copy in sync with the latest revision in the repository.

$ svn update U  foo.c U  bar.c Updated to revision 2.

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

Let's examine the output of svn 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 Subversion performed to bring your working copy up-to-date:


U foo

File foo was Updated (received changes from the server).


A foo

File or directory foo was Added to your working copy.


D foo

File or directory foo was Deleted from your working copy.


R foo

File 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 repository considers them to be distinct objects with distinct histories.


G foo

File foo received new changes from the repository, but your local copy of the file had your modifications. The changes did not intersect, however, so Subversion has merGed the repository's changes into the file without a problem.


C foo

File 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.

3.5.2 Make Changes to Your Working Copy

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 use here are svn add, svn delete, svn copy, and svn move. However, if you are merely editing a file (or files) that is already in Subversion, you may not need to use any of these commands until you commit. Changes you can make to your working copy:


File changes

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.


Tree changes

You can ask Subversion 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 happen in the repository until you commit them.

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 and just as efficiently, too.

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


svn add foo

Schedule foo to be added to the repository. When you next commit, foo becomes 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 schedule foo itself, pass the --non-recursive (-N) switch.


svn delete foo

Schedule foo to be deleted from the repository. If foo is a file, it is immediately deleted from your working copy. If foo is a directory, it is not deleted, but Subversion schedules it for deletion. When you commit your changes, foo will be removed from your working copy and the repository.

Of course, nothing is ever totally deleted from the repository just from the HEAD of the repository. You can get back anything you delete by checking out (or updating your working copy of) a revision earlier than the one in which you deleted it.


svn copy foo bar

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


svn move foo bar

This command is exactly the same as running svn copy foo bar; svn delete foo. That is, bar is scheduled for addition as a copy of foo, and foo is scheduled for removal. svn move does not create intermediate directories.

Changing the Repository Without a Working Copy

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 there are 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 svn mkdir, svn copy, svn move, and svn delete can work with URLs.

URL operations behave in this manner because commands that operate on a working copy can use the working copy as a sort of staging area 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 previously mentioned actions represent an immediate commit.


3.5.3 Examine Your Changes

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 svn status, svn diff, and svn 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.

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 pristine copy of each version controlled file within the .svn 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.

3.5.3.1 svn status

You'll probably use the svn status command more than any other Subversion command.

CVS Users: Hold That Update!

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

In Subversion, update does just that 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 update command to see what local modifications you've made.


If you run svn status 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 svn status can return. (Note that the text following # in the following example is not actually printed by svn status.)

$ 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 ?      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 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 ...

In this output format svn status 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 as follows:


A file_or_dir

The file or directory file_or_dir has been scheduled for addition into the repository.


C file

file_or_dir 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.


D file_or_dir

The file or directory file_or_dir has been scheduled for deletion from the repository.


M file

The contents of file file have been modified.


X dir

The directory dir is unversioned, but is related to a Subversion externals definition. To find out more about externals definitions, see Section 7.3.


? file_or_dir

The file or directory file_or_dir is not under version control. You can silence the question marks by either passing the --quiet (-q) switch to svn status, or by setting the svn:ignore property on the parent directory. For more information on ignored files, see Section 7.2.3.3.


! file_or_dir

The file or directory file_or_dir 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 svn update will refetch the file or directory from the repository, or svn revert file will restore a missing file.


~ file_or_dir

The file or directory file_or_dir 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 svn delete or svn add commands.

The second column tells the status of a file or directory's properties (see Section 7.2 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 only shows whitespace or an L, which means that Subversion has locked the item in the .svn working area. You see an L if you run svn status in a directory where an svn commit is in progress 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 svn cleanup (more about that later in this chapter).

The fourth column only shows a + or whitespace, which means that the file or directory is scheduled to be added or modified with additional attached history. This typically happens when you svn move or svn 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 was 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 is added-with-history (copied), which means this file automatically exists in the copy. Then the local modifications are uploaded into the copy.

The fifth column only shows an S or whitespace. This signifies that the file or directory has been switched from the path of the rest of the working copy (using svn switch) to a branch.

If you pass a specific path to svn status, it gives you information about that item alone:

$ svn status stuff/fish.c D      stuff/fish.c

svn 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:

$ 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

This is the long form output of svn 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 previously mentioned invocations to svn status contact the repository; they work only locally by comparing the metadata in the .svn directory with the working copy. Finally, there is the --show-updates (-u) switch, which contacts the repository and adds information about things that are out-of-date:

$ 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

Notice the two asterisks: if you were to run svn 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 repository will reject your commit for being out-of-date. (More on this subject later.)

3.5.3.2 svn diff

Another way to examine your changes is with the svn diff command. You can find out exactly how you've modified things by running svn diff with no arguments, which prints out file changes in unified diff format:[1]

[1] 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 --diff-cmd and pass any flags you'd like to it using the --extensions switch. For example, to see local differences in file foo.c in context output format while ignoring whitespace changes, you might run svn diff --diff-cmd /usr/bin/diff --extensions `-bc' foo.c.

$ svn diff Index: bar.c = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = --- bar.c        (revision 3) +++ bar.c        (working copy) @@ -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;  } 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.

The svn diff command produces this output by comparing your working files against the cached pristine copies within the .svn area. 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 +. the svn diff command also prints filename and offset information useful to the patch program, so you can generate patches by redirecting the diff output to a file:

$ svn diff > patchfile

For example, you could email the patchfile to another developer for review or testing prior to commit.

3.5.3.3 svn revert

Now suppose you see the previous 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 svn revert.

$ svn revert README Reverted 'README'

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

$ svn status foo ?      foo $ svn add foo A         foo $ svn revert foo Reverted 'foo' $ svn status foo ?      foo

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


Or perhaps you mistakenly removed a file from version control:

$ svn status README         README $ svn delete README  D         README $ svn revert README Reverted 'README' $ svn status README        README

3.5.4 Resolve Conflicts (Merging Others' Changes)

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

$ svn update U  INSTALL G  README C  bar.c Updated to revision 46.

The U and G codes are no cause for concern; those files cleanly absorbed changes from the repository. 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 repository didn't overlap in any way.

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

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

  • Subversion prints a C during the update, and remembers that the file is in a state of conflict.

  • Subversion places conflict markers special strings of text which delimit the sides of the conflict into the file to visibly demonstrate the overlapping areas.

  • For every conflicted file, Subversion places three extra files in your working copy:


    filename.mine

    This is your file as it existed in your working copy before you updated your working copy that is, without conflict markers. This file has your latest changes in it and nothing else.


    filename.rOLDREV

    This is the file that was the BASE revision before you updated your working copy. That is, the file that you checked out before you made your latest edits.


    filename.rNEWREV

    This is the file that your Subversion client just received from the server when you updated your working copy. This file corresponds to the HEAD revision of the repository.

    Here OLDREV is the revision number of the file in your .svn directory and NEWREV is the revision number of the repository HEAD.

For example, Sally makes changes to the file sandwich.txt 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:

$ svn update C  sandwich.txt Updated to revision 2. $ ls -1 sandwich.txt sandwich.txt.mine sandwich.txt.r1 sandwich.txt.r2

At this point, Subversion will not allow you to commit the file sandwich.txt until the three temporary files are removed.

$ 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

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).

  • Copy one of the temporary files on top of your working file.

  • Run svn revert <filename> to throw away all of your local changes.

Once you've resolved the conflict, you need to let Subversion know by running svn resolved. This removes the three temporary files and Subversion no longer considers the file to be in a state of conflict.[2]

[2] You can always remove the temporary files yourself, but would you really want to do that when Subversion can do it for you?

$ svn resolved sandwich.txt Resolved conflicted state of 'sandwich.txt'

3.5.4.1 Merging conflicts by hand

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 are 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 Provolone <<<<<<< .mine Salami Mortadella Prosciutto = = = = = = = Sauerkraut Grilled Chicken >>>>>>> .r2 Creole Mustard Bottom piece of bread

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:

<<<<<<< .mine Salami Mortadella Prosciutto = = = = = = =

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

= = = = = = = Sauerkraut Grilled Chicken >>>>>>> .r2

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.[3] Once you've agreed on the changes you will check in, edit your file and remove the conflict markers.

[3] And if you ask them for it, they may very well ride you out of town on a rail.

Top piece of bread Mayonnaise Lettuce Tomato Provolone Salami Mortadella Prosciutto Creole Mustard Bottom piece of bread

Now run svn resolved, and you're ready to commit your changes:

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

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 including your file as it was before you updated. You can even use a third-party interactive merging tool to examine those three files.

3.5.4.2 Copying a file onto your working file

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:

$ 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

3.5.4.3 Punting: Using svn revert

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:

$ svn revert sandwich.txt Reverted 'sandwich.txt' $ ls sandwich.* sandwich.txt

Note that when you revert a conflicted file, you don't have to run svn resolved.

Now you're ready to check in your changes. Note that svn 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 svn resolved when you're certain that you've fixed the conflict in your file once the temporary files are removed, Subversion will let you commit the file even if it still contains conflict markers.

3.5.5 Commit Your Changes

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

The svn commit command sends all of your changes to the repository. 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) option:

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

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 --file switch:

$ svn commit --file logmsg  Sending        sandwich Transmitting file data . Committed revision 4.

If you fail to specify either the --message or --file switch, then Subversion will automatically launch your favorite editor (as defined in the environment variable $EDITOR) 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.

$ svn commit Waiting for Emacs...Done Log message unchanged or not specified a)bort, c)ontinue, e)dit a $


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 has done that, the entire commit will fail with a message informing you that one or more of your files is out-of-date:

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

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

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.



Version Control with Subversion
Version Control with Subversion
ISBN: 0596510330
EAN: 2147483647
Year: 2003
Pages: 127

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net