| |
| @c Subversion for CVS Users |
| |
| @setfilename svn_for_cvs_users.info |
| @settitle Subversion for CVS Users |
| @setchapternewpage odd |
| @paragraphindent 0 |
| |
| @c Browser defaults lose. Let's go for black text on white background. |
| @ifhtml |
| @html |
| <body bgcolor="#FFFFFF" fgcolor="#000000"> |
| @end html |
| @end ifhtml |
| |
| @titlepage |
| @title @titlefont{Subversion for CVS Users} |
| @author Subversion Development Project @url{http://subversion.tigris.org} |
| @end titlepage |
| |
| |
| |
| @ifinfo |
| A Subversion quick-start guide for CVS users. |
| @end ifinfo |
| |
| |
| @menu |
| * Introduction:: |
| * Revision numbers are different now:: |
| * More "disconnected" operations:: |
| * Distinction between 'status' and 'update':: |
| * Properties:: |
| * Directory versioning:: |
| * Conflicts:: |
| * Binary files:: |
| * Committing:: |
| * Branches and tags:: |
| * Real docs:: |
| @end menu |
| |
| @c ----------------------------------------------------- |
| |
| @node Introduction |
| @section Introduction |
| |
| This document is meant to be a quick-start guide for CVS users new to |
| Subversion. It's not a substitute for real documentation and manuals; |
| but it should give you a quick conceptual 'diff' when switching over. |
| |
| The goal of Subversion is to take over the current and future CVS user |
| base. Subversion not only includes new features, but attempts to fix |
| certain "broken" behaviors that CVS had. This means that you may be |
| encouraged to break certain habits -- ones that you forgot were odd to |
| begin with. |
| |
| |
| |
| @node Revision numbers are different now |
| @section Revision numbers are different now |
| |
| In CVS, revision numbers are per-file. This is because CVS uses RCS |
| as a backend; each file has a corresponding RCS file in the |
| repository, and the repository is roughly laid out according to |
| structure of your project tree. |
| |
| In Subversion, the repository looks like a single filesystem. Each |
| commit results in an entirely new filesystem tree; in essence, the |
| repository is an array of trees. Each of these trees is labeled with |
| a single revision number. When someone talks about "revision 54", |
| they're talking about a particular tree (and indirectly, the way the |
| filesystem looked after the 54th commit.) |
| |
| Technically, it's not valid to talk about "revision 5 of foo.c". |
| Instead, one would say "foo.c as it appears in revision 5". Also, be |
| careful when making assumptions about the evolution of a file. In |
| CVS, revisions 5 and 6 of foo.c are always different. In Subversion, |
| it's most likely that foo.c did *not* change between revisions 5 and |
| 6. |
| |
| |
| @node More "disconnected" operations |
| @section More "disconnected" operations |
| |
| In recent years, disk space has become outrageously cheap and |
| abundant, but network bandwidth has not. Therefore, the Subversion |
| working copy has been optimized around the scarcer resource. |
| |
| The .svn/ administrative directory serves the same purpose as the CVS/ |
| one, except that it also stores "pristine" copies of files. This |
| allows you to do many things off-line: |
| |
| @itemize @bullet |
| @item 'svn status' |
| shows you local modifications (see below) |
| @item 'svn diff' |
| shows you the details of your modifications |
| @item 'svn ci' |
| sends differences to the repository (CVS only sends fulltexts!) |
| @item 'svn revert' |
| removes your modifications |
| @end itemize |
| |
| This last subcommand is new; it will not only remove local mods, but |
| it will un-schedule operations such as adds and deletes. It's the |
| preferred way to revert a file; running 'rm file; svn up' will still |
| work, but it blurs the purpose of updating. And, while we're on this |
| subject... |
| |
| |
| @node Distinction between 'status' and 'update' |
| @section Distinction between 'status' and 'update' |
| |
| In Subversion, we've tried to erase a lot of the confusion between the |
| 'status' and 'update' subcommands. |
| |
| The 'status' command has two purposes: (1) to show the user any local |
| modifications in the working copy, and (2) to show the user which |
| files are out-of-date. Unfortunately, because of CVS's hard-to-read |
| output, many CVS users don't take advantage of this command at all. |
| Instead, they've developed a habit of running 'cvs up' to quickly see |
| their mods. Of course, this has the side effect of merging repository |
| changes that you may not be ready to deal with! |
| |
| With Subversion, we've tried to remove this muddle by making the |
| output of 'svn status' easy to read for humans and parsers. Also, |
| 'svn update' only prints information about files that are updated, |
| @emph{not} local modifications. |
| |
| Here's a quick guide to 'svn status'. We encourage all new Subversion |
| users to use it early and often: |
| |
| @itemize @bullet |
| @item 'svn status' |
| prints all files that have local modifications; the network is not |
| accessed by default. |
| @itemize @bullet |
| @item -u switch |
| add out-of-dateness information from repository |
| @item -v switch |
| show @emph{all} entries under version control |
| @item -n switch |
| nonrecursive |
| @end itemize |
| @end itemize |
| |
| The status command has two output formats. In the default "short" |
| format, local mods look like this: |
| |
| @example |
| % svn status |
| M ./foo.c |
| M ./bar/baz.c |
| @end example |
| |
| If you specify either the -u or -v switch, a "long" format is used: |
| |
| @example |
| % svn status |
| M 1047 ./foo.c |
| _ * 1045 ./faces.html |
| _ * - ./bloo.png |
| M 1050 ./bar/baz.c |
| Head revision: 1066 |
| @end example |
| |
| In this case, two new columns appear. The first column potentially |
| contains an asterisk, which means that the file or directory is |
| out-of-date. The second column shows the working-copy's revision |
| number of the item. In the example above, the asterisk indicates that |
| `faces.html' would be patched if we updated, and that `bloo.png' is a |
| newly added file in the repository. (The '-' next to bloo.png means |
| that it doesn't yet exist in the working copy.) |
| |
| Lastly, here's a quick summary of status codes that you may see: |
| |
| @example |
| A Add |
| D Delete |
| R Replace (delete, then re-add) |
| M local Modification |
| U Updated |
| G merGed |
| C Conflict |
| @end example |
| |
| Subversion has combined the CVS 'P' and 'U' codes into just 'U'. When |
| a merge or conflict occurs, Subversion simply prints 'G' or 'C', |
| rather than a whole sentence about it. |
| |
| |
| @node Properties |
| @section Properties |
| |
| A new feature of Subversion is that you can attach arbitrary metadata to |
| files and directories. We refer to this data as @dfn{properties}, and |
| they can be thought of as collections of name/value pairs (hashtables) |
| attached to each item in your working copy. |
| |
| To set or get a property name, use the 'svn propset' and 'svn propget' |
| subcommands. To list all properties on an object, use 'svn proplist'. |
| |
| Properties are @emph{versioned}, just like file contents. This means |
| that new properties can be merged into your working files, and can |
| sometimes come into conflict too. |
| |
| Certain property names are standardized and used by Subversion to |
| track important data; these property names all begin with an "svn:" |
| prefix. For example: "svn:mime-type" indicates the file's mime-type, |
| "svn:perms" describe what a file's permissions should be. On a |
| directory, the "svn:ignore" property contains a list of patterns that |
| you would normally see in a .cvsignore file. Of course they're |
| editable by users; just be sure you know what they do. |
| |
| Finally, we should point out that the 'svn status' and 'svn update' |
| commands have ways of telling you about properties: |
| |
| @example |
| __ |
| _M |
| _U |
| UU |
| @end example |
| |
| The letter codes printed by these subcommands actually have two parts: |
| file-contents and properties. The first example indicates that the |
| file has properties as well as text -- but that there's nothing |
| special about either portion. The second example is status's way of |
| reminding you that you have some locally modified properties on a file |
| (but the text is unchanged.) The third example is update's way of |
| telling you that a file's properties were patched (but not its text). |
| The fourth example means that both components were patched. |
| |
| |
| @node Directory versioning |
| @section Directory versioning |
| |
| Subversion tracks tree structures, not just file contents. It's one |
| of the biggest reasons Subversion was written to replace CVS. |
| |
| Here's what this means to you: |
| |
| @itemize @bullet |
| @item |
| the 'svn add' and 'svn rm' commands work on directories now, just |
| as they work on files. However, these commands do *not* cause |
| any kind of immediate change in the repository. Instead, the |
| working directory is recursively "scheduled" for addition or |
| deletion. No repository changes happen until you commit. |
| @item |
| Directories aren't dumb containers anymore; they have revision |
| numbers like files. (Or more properly, it's correct to talk |
| about "directory foo/ in revision 5".) |
| @end itemize |
| |
| Let's talk more about that last point. Directory versioning is a Hard |
| Problem. Because we want to allow mixed-revision working copies, |
| there are some limitations on how far we can abuse this model. |
| |
| From a theoretical point of view, we define "revision 5 of directory |
| foo" to mean a specific collection of directory-entries and |
| properties. Now suppose we start adding and removing files from foo, |
| and then commit. It would be a lie to say that we still have revision |
| 5 of foo. However, if we bumped foo's revision number after the |
| commit, that would be a lie too; there may be other changes to foo we |
| haven't yet received, because we haven't updated yet. |
| |
| Subversion deals with this problem by quietly tracking committed adds |
| and deletes in the .svn/ area. When you eventually run 'svn update', |
| all accounts are settled with the repository, and the directory's new |
| revision number is set correctly. @b{Therefore, only after an update is |
| it truly safe to say that you have a "perfect" revision of a directory.} |
| Most of the time, your working copy will contain "imperfect" directory |
| revisions. |
| |
| Similarly, a problem arises if you attempt to commit property changes on |
| a directory. Normally, the commit would bump the working directory's |
| local revision number. But again, that would be a lie, because there |
| may be adds or deletes that the directory doesn't yet have, because no |
| update has happened. @b{Therefore, you are not allowed to commit |
| property-changes on a directory unless the directory is up-to-date.} |
| |
| Go ahead and enjoy directory versioning; just file away those two |
| warnings somewhere in the back of your mind. Somewhere down the line, |
| they may help you understand what's happening in your working copy. |
| |
| |
| @node Conflicts |
| @section Conflicts |
| |
| CVS marks conflicts with in-line "conflict markers", and prints a 'C' |
| during an update. Historically, this has caused problems. Many users |
| forget about (or don't see) the 'C' after it whizzes by their |
| terminal. They often forget that the conflict-markers are even |
| present, and then accidentally commit garbaged files. |
| |
| Subversion solves this problem by making conflicts more tangible. If |
| a conflict happens during an update, three things happen: |
| |
| @itemize @bullet |
| @item |
| a 'C' is printed during the update |
| @item |
| a reject file ('.rej') is created that contains the conflicting text |
| @item |
| the file is marked as conflicted in .svn/entries |
| @end itemize |
| |
| At this point, Subversion will @emph{not} allow you to commit the file |
| until you hand-remove the associated .rej file. So it's potentially |
| safe to forget about the conflict; 'svn ci' will remind you later on. |
| |
| If you get a conflict, you can hand-merge the conflicted text and then |
| remove the .rej file. Or, if you simply want toss all of your local |
| mods, the 'svn revert' command will do that for you -- along with |
| deleting the .rej file. |
| |
| Finally, it's worth mentioning that properties can come into |
| conflict. If this happens, a description of the conflict will be |
| dumped into '.prej' file instead. |
| |
| |
| @node Binary files |
| @section Binary files |
| |
| CVS users have to mark binary files with '-kb' flags, to prevent data |
| from being munged (due to keyword expansion and line-ending |
| translations.) They sometimes forget to do this. |
| |
| Subversion examines the "svn:mime-type" property to decide if a file |
| is text or binary. If the file has no "svn:mime-type" property, |
| Subversion assumes it is text. If the file has the "svn:mime-type" |
| property set to anything other than "text/*", it assumes the file is |
| binary. |
| |
| Subversion also helps users by running a binary-detection algorithm in |
| the 'svn import' and 'svn add' subcommands. These subcommands will |
| make a good guess and then (possibly) set a binary "svn:mime-type" |
| property on the file being added. (If Subversion guesses wrong, you |
| can always remove or hand-edit the property.) |
| |
| As in CVS, binary files are not subject to keyword expansion or |
| line-ending conversions. Also, when a binary file is "merged" during |
| update, no real merge occurs. Instead, Subversion creates two files |
| side-by-side in your working copy; the one containing your local |
| modifications is renamed with an ".orig" extension. |
| |
| |
| |
| @node Committing |
| @section Committing |
| |
| Unlike CVS, SVN can handle anonymous and authorized users in the same |
| repository. There is no need for an anonymous user or a separate |
| repository. If the SVN server requests authorization when committing, |
| the client should prompt you for your authorization (password). |
| |
| Also, the command-line client does not currently bring up an editor. |
| Therefore, you must write the log entry @b{before} committing and |
| pass the log file path when committing: |
| |
| @example |
| svn commit -F <path to your new log entry> |
| @end example |
| |
| |
| |
| @node Branches and tags |
| @section Branches and tags |
| |
| Sit down and prepare yourself for this last topic. It may take a |
| minute to bend your mind around this idea. |
| |
| In the first section, we mentioned how each commit creates an entire |
| new filesystem tree in the repository. Really, as you may have |
| suspected, the filesystem doesn't grow 652 new inodes each time this |
| happens! Instead, each new tree is mostly made of pointers to |
| existing nodes; new nodes are created only for changed items. |
| |
| This technique demonstrates how the filesystem is able to make |
| "cheap copies" of things. Remember that nodes are never, ever deleted |
| in the filesystem; at most, they're simply unlinked from the head tree |
| (and they continue to stay linked to older trees.) These cheap copies |
| are nothing more than directory entries that point to existing nodes. |
| And this is the basis of tags and branches. |
| |
| Suppose we have a have a repository whose head tree is revision 82. In |
| this repository is a subdirectory 'mooIRC' that contains a software |
| project that is ready to be tagged. How do we tag it? Very simple: |
| make a cheap copy of this directory. In other words, create a new |
| directory entry (somewhere else in the filesystem) that points to this |
| @emph{specfic} revision of the directory 'mooIRC'. Of course, you can |
| name that new directory entry whatever you want -- probably a tag-name |
| like 'mooIRC-beta'. |
| |
| Now, as long as you never touch the contents of the directory |
| 'mooIRC-beta', it will forever point to a directory that looks the way |
| mooIRC/ did at a specific moment in time (however it looked in |
| revision 82). That's a tag. |
| |
| But what if you start making commits in mooIRC-beta? And what if you |
| also continue to make commits in the original mooIRC directory? Then |
| you have two directories that started out looking identical -- their |
| common ancestor was mooIRC in revision 82 -- but now have diverged |
| their contents over time. In other words, they represent different |
| branches of the project. |
| |
| It's very important to note that the Subversion filesystem is not |
| aware of "tags" or "branches". It's only aware of directories, and |
| all directories are equal. The tag and branch concepts are purely |
| @emph{human} meanings attached to particular directories. |
| |
| For this reason, it's up to users (and the Subversion repository |
| administrator) to choose sane policies that help elucidate these |
| labels. For example, here's a good way to lay out your repository: |
| |
| @example |
| / |
| /projectA |
| /projectA/trunk/ |
| /projectA/branches/ |
| /projectA/tags/ |
| /projectB |
| /projectB/trunk/ |
| /projectB/branches/ |
| /projectB/tags/ |
| @end example |
| |
| Each time /projectA/trunk reaches a taggable state, make a copy of the |
| directory somewhere in /projectA/tags/, and set the copy to |
| read-only. Use the same procedure to create a branch in |
| /projectA/branches/. |
| |
| |
| @node Real docs |
| @section Real docs |
| |
| Better, more detailed documentation exists than this paper. Go to the |
| Subversion website (@url{http://subversion.tigris.org}) and look in the |
| "docs" section. (Or look in the 'doc/' directory of the Subversion |
| source tree.) |
| |
| Specifically, a user manual is in progress, and a design specification |
| exists for programmers. |
| |