This documentation was written to describe Subversion 1.5. If you are running a newer version of Subversion, we strongly suggest that you visithttp://www.svnbook.com/ and consult the version of this book appropriate for your version of Subversion.
Subversion has numerous features, options, bells, and whistles, but on a day-to-day basis, odds are that you will use only 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.
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
Possibly undo some changes.
svn revert
Resolve conflicts (merge others' changes).
svn update
svn resolve
Commit your changes.
svn commit
When working on a project with a team, you'll want to update your working copy to receive any changes other developers on the project have made since your last update. Usesvn update to bring your working copy into sync with the latest revision in the repository:
$ svn updateU foo.cU bar.cUpdated to revision 2.
In this case, it appears that someone checked in modifications to bothfoo.c andbar.c since the last time you updated, and Subversion has updated your working copy to include those changes.
When the server sends changes to your working copy viasvn update, 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. To find out what these letters mean, runsvn help update.
Now you can get to work and make changes in your working copy. It's usually most convenient to decide on a discrete change (or set of changes) to make, such as writing a new feature, fixing a bug, and so on. The Subversion commands that you will use here aresvn add,svn delete,svn copy,svn move, andsvn mkdir. 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.
You can make two kinds of changes to your working copy:file changes andtree changes. You don't need to tell Subversion that you intend to change a file; just make your changes using your text editor, word processor, graphics program, or whatever tool you would normally use. Subversion automatically detects which files have been changed, and in addition, it handles binary files just as easily as it handles text files—and just as efficiently, too. For tree changes, you can ask Subversion to “mark” files and directories for scheduled removal, addition, copying, or moving. These changes may take place immediately in your working copy, but no additions or removals will happen in the repository until you commit them.
Versioning Symbolic Links
On non-Windows platforms, Subversion is able to version files of the special typesymbolic link (or “symlink”). A symlink is a file that acts as a sort of transparent reference to some other object in the filesystem, allowing programs to read and write to those objects indirectly by way of performing operations on the symlink itself.
When a symlink is committed into a Subversion repository, Subversion remembers that the file was in fact a symlink, as well as the object to which the symlink “points.” When that symlink is checked out to another working copy on a non-Windows system, Subversion reconstructs a real filesystem-level symbolic link from the versioned symlink. But that doesn't in any way limit the usability of working copies on systems such as Windows that do not support symlinks. On such systems, Subversion simply creates a regular text file whose contents are the path to which to the original symlink pointed. While that file can't be used as a symlink on a Windows system, it also won't prevent Windows users from performing their other Subversion-related activities.
Here is an overview of the five Subversion subcommands that you'll use most often to make tree changes:
svn add fooSchedule file, directory, or symbolic linkfoo to be added to the repository. When you next commit,foo will become a child of its parent directory. Note that iffoo is a directory, everything underneathfoo will be scheduled for addition. If you want only to addfoo itself, pass the--depth empty option.
svn delete fooSchedule file, directory, or symbolic linkfoo to be deleted from the repository. Iffoo is a file or link, it is immediately deleted from your working copy. Iffoo is a directory, it is not deleted, but Subversion schedules it for deletion. When you commit your changes,foo will be entirely removed from your working copy and the repository.[4]
svn copy foo barCreate a new itembar as a duplicate offoo and automatically schedulebar for addition. Whenbar is added to the repository on the next commit, its copy history is recorded (as having originally come fromfoo).svn copy does not create intermediate directories unless you pass the--parents option.
svn move foo barThis command is exactly the same as runningsvn copy foo bar; svn delete foo. That is,bar is scheduled for addition as a copy offoo, andfoo is scheduled for removal.svn move does not create intermediate directories unless you pass the--parents option.
svn mkdir blortThis command is exactly the same as runningmkdir blort; svn add blort. That is, a new directory namedblort is created and scheduled for addition.
Changing the Repository Without a Working Copy
Thereare some use cases that immediately commit tree changes to the repository. This happens only when a subcommand is operating directly on a URL, rather than on a working-copy path. In particular, specific uses ofsvn mkdir,svn copy,svn move, andsvn delete can work with URLs (and don't forget thatsvn import always makes changes to a URL).
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 aforementioned actions represents an immediate commit.
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 an overview of the changes you've made by usingsvn status, and dig into the details of those changes by usingsvn diff.
Look Ma! No Network!
You can use the commandssvn status,svn diff, andsvn revert without any network access even if your repositoryis across the network. 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.[5]
Subversion does this by keeping private caches of pristine versions of each versioned file inside the.svn administrative areas. This allows Subversion to report—and revert—local modifications to those fileswithout network access. This cache (called the “text-base”) also allows Subversion to send the user's local modifications during a commit to the server as a compresseddelta (or “difference”) against the pristine version. Having this cache is a tremendous benefit—even if you have a fast Internet connection, it's much faster to send only a file's changes rather than the whole file to the server.
Subversion has been optimized to help you with this task, and it is able to do many things without communicating with the repository. In particular, your working copy contains a hidden 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.
To get an overview of your changes, you'll use thesvn status command. You'll probably usesvn status more than any other Subversion command.
CVS Users: Hold That Update!
You're probably used to usingcvs 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,svn update does just that—it updates your working copy with any changes committed to the repository since the last time you updated your working copy. You may have to break the habit of using theupdate command to see what local modifications you've made.
If you runsvn status at the top of your working copy with no arguments, it will detect all file and tree changes you've made. Here are a few examples of the most common status codes thatsvn status can return. (Note that the text following# is not actually printed bysvn status.)
? scratch.c # file is not under version controlA stuff/loot/bloo.h # file is scheduled for additionC stuff/loot/lump.c # file has textual conflicts from an updateD stuff/fish.c # file is scheduled for deletionM bar.c # the content in bar.c has local modifications
In this output format,svn status prints six 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 we listed are:
A itemThe file, directory, or symbolic linkitem has been scheduled for addition into the repository.
C itemThe fileitem 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 (and weren't resolved during the update). You must resolve this conflict before committing your changes to the repository.
D itemThe file, directory, or symbolic linkitem has been scheduled for deletion from the repository.
M itemThe contents of the fileitem have been modified.
If you pass a specific path tosvn status, you get information about that item alone:
$ svn status stuff/fish.cD stuff/fish.c
svn status also has a--verbose (-v) option, which will show you the status ofevery item in your working copy, even if it has not been changed:
$ svn status -vM 44 23 sally README 44 30 sally INSTALLM 44 20 harry bar.c 44 18 ira stuff 44 35 harry stuff/trout.cD 44 19 ira stuff/fish.c 44 21 sally stuff/thingsA 0 ? ? stuff/things/bloo.h 44 36 harry stuff/things/gloo.c
This is the “long form” output ofsvn status. The letters in the first column mean the same as before, 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 prior invocations tosvn status contact the repository—instead, they compare the metadata in the.svn directory with the working copy. Finally, there is the--show-updates (-u) option, which contacts the repository and adds information about things that are out of date:
$ svn status -u -vM * 44 23 sally READMEM 44 20 harry bar.c * 44 35 harry stuff/trout.cD 44 19 ira stuff/fish.cA 0 ? ? stuff/things/bloo.hStatus against revision: 46
Notice the two asterisks: if you were to runsvn update at this point, you would receive changes toREADME andtrout.c. This tells you some very useful information—you'll need to update and get the server changes onREADME before you commit, or the repository will reject your commit for being out of date (more on this subject later).
svn status can display much more information about the files and directories in your working copy than we've shown here—for an exhaustive description ofsvn status and its output, seesvn status.
Another way to examine your changes is with thesvn diff command. You can find outexactly how you've modified things by runningsvn diff with no arguments, which prints out file changes inunified diff format:
$ svn diffIndex: 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.Thesvn 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-, and added lines are prefaced with+.svn diff also prints filename and offset information useful to thepatch program, so you can generate “patches” by redirecting the diff output to a file:
$ svn diff > patchfile
You could, for example, email the patch file to another developer for review or testing prior to a commit.
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 (-x) option. For example, to see local differences in filefoo.c in context output format while ignoring case differences, you might runsvn diff --diff-cmd /usr/bin/diff --extensions '-i' foo.c.
Suppose while viewing the output ofsvn diff you determine that all the changes you made to a particular file are mistakes. Maybe you shouldn't have changed the file at all, or perhaps it would be easier to make different changes starting from scratch.
This is a perfect opportunity to usesvn revert:
$ svn revert READMEReverted 'README'
Subversion reverts the file to its premodified state by overwriting it with the cached “pristine” copy from the.svn area. But also note thatsvn revert can undoany 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 fooA foo$ svn revert fooReverted 'foo'$ svn status foo? foo
svn revert has exactly the same effect as deletingitemitem from your working copy and then runningsvn update -r BASE. 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.item
Or perhaps you mistakenly removed a file from version control:
$ svn status README$ svn delete READMED README$ svn revert READMEReverted 'README'$ svn status README
We've already seen howsvn status -u can predict conflicts. Suppose you runsvn update and some interesting things occur:
$ svn updateU INSTALLG READMEConflict discovered in 'bar.c'.Select: (p) postpone, (df) diff-full, (e) edit, (h) help for more options:
TheU andG codes are no cause for concern; those files cleanly absorbed changes from the repository. The files marked withU contained no local changes but wereUpdated with changes from the repository. TheG stands for merGed, which means that the file had local changes to begin with, but the changes coming from the repository didn't overlap with the local changes.
But the next two lines are part of a feature (new in Subversion 1.5) calledinteractive conflict resolution. This means that the changes from the server overlapped with your own, and you have the opportunity to resolve this conflict. The most commonly used options are displayed, but you can see all of the options by typingh:
… (p) postpone - mark the conflict to be resolved later (df) diff-full - show all changes made to merged file (e) edit - change merged file in an editor (r) resolved - accept merged version of file (mf) mine-full - accept my version of entire file (ignore their changes) (tf) theirs-full - accept their version of entire file (lose my changes) (l) launch - launch external tool to resolve conflict (h) help - show this list
Let's briefly review each of these options before we go into detail on what each option means.
p)ostponeLeave the file in a conflicted state for you to resolve after your update is complete.
d)iffDisplay the differences between the base revision and the conflicted file itself in unified diff format.
e)ditOpen the file in conflict with your favorite editor, as set in the environment variableEDITOR.
r)esolvedAfter editing a file, tellsvn that you've resolved the conflicts in the file and that it should accept the current contents—basically that you've “resolved” the conflict.
m)ine-(f)ullDiscard the newly received changes from the server and use only your local changes for the file under review.
t)heirs-(f)ullDiscard your local changes to the file under review and use only the newly received changes from the server.
l)aunchLaunch an external program to perform the conflict resolution. This requires a bit of preparation beforehand.
h)elpShow the list of all possible commands you can use in interactive conflict resolution.
We'll cover these commands in more detail now, grouping them together by related functionality.
Before deciding how to attack a conflict interactively, odds are that you'd like to see exactly what is in conflict, and thediff command (d) is what you'll use for this:
…Select: (p) postpone, (df) diff-full, (e) edit, (h)elp for more options : d--- .svn/text-base/sandwich.txt.svn-base Tue Dec 11 21:33:57 2007+++ .svn/tmp/tempfile.32.tmp Tue Dec 11 21:34:33 2007@@ -1 +1,5 @@-Just buy a sandwich.+<<<<<<< .mine+Go pick up a cheesesteak.+=======+Bring me a taco!+>>>>>>> .r32…
The first line of the diff content shows the previous contents of the working copy (theBASE revision), the next content line is your change, and the last content line is the change that was just received from the server (usually theHEAD revision). With this information in hand, you're ready to move on to the next action.
There are four different ways to resolve conflicts interactively—two of which allow you to selectively merge and edit changes, and two of which allow you to simply pick a version of the file and move along.
If you wish to choose some combination of your local changes, you can use the “edit” command (e) to manually edit the file with conflict markers in a text editor (determined by theEDITOR environment variable). Editing the file by hand in your favorite text editor is a somewhat low-tech way of remedying conflicts (seethe section called “Merging conflicts by hand” for a walkthrough), so some people like to use fancy graphical merge tools instead.
To use a merge tool, you need to either set theSVN_MERGE environment variable or define themerge-tool-cmd option in your Subversion configuration file (seethe section called “Configuration Options” for more details). Subversion will pass four arguments to the merge tool: theBASE revision of the file, the revision of the file received from the server as part of the update, the copy of the file containing your local edits, and the merged copy of the file (which contains conflict markers). If your merge tool is expecting arguments in a different order or format, you'll need to write a wrapper script for Subversion to invoke. After you've edited the file, if you're satisfied with the changes you've made, you can tell Subversion that the edited file is no longer in conflict by using the “resolve” command (r).
If you decide that you don't need to merge any changes, but just want to accept one version of the file or the other, you can either choose your changes (a.k.a. “mine”) by using the “mine-full” command (mf) or choose theirs by using the “theirs-full” command (tf).
This may sound like an appropriate section for avoiding marital disagreements, but it's actually still about Subversion, so read on. If you're doing an update and encounter a conflict that you're not prepared to review or resolve, you can typep to postpone resolving a conflict on a file-by-file basis when you runsvn update. If you're running an update and don't want to resolve any conflicts, you can pass the--non-interactive option tosvn update, and any file in conflict will be marked with aC automatically.
TheC stands forconflict. This means that the changes from the server overlapped with your own, and now you have to manually choose between them after the update has completed. When you postpone a conflict resolution,svn typically does three things to assist you in noticing and resolving that conflict:
Subversion prints aC during the update and remembers that the file is in a state of conflict.
If Subversion considers the file to be mergeable, it placesconflict markers—special strings of text that delimit the “sides” of the conflict—into the file to visibly demonstrate the overlapping areas. (Subversion uses thesvn:mime-type property to decide whether a file is capable of contextual, line-based merging. Seethe section called “File Content Type” to learn more.)
For every conflicted file, Subversion places three extra unversioned files in your working copy:
filename.mineThis is your file as it existed in your working copy before you updated your working copy—that is, without conflict markers. This file has only your latest changes in it. (If Subversion considers the file to be unmergeable, the.mine file isn't created, since it would be identical to the working file.)
filename.rOLDREVThis is the file that was theBASE revision before you updated your working copy. That is, the file that you checked out before you made your latest edits.
filename.rNEWREVThis is the file that your Subversion client just received from the server when you updated your working copy. This file corresponds to theHEAD revision of the repository.
HereOLDREV is the revision number of the file in your.svn directory, andNEWREV is the revision number of the repositoryHEAD.
For example, Sally makes changes to the filesandwich.txt, but does not yet commit those changes. Meanwhile, Harry commits changes to that same file. Sally updates her working copy before committing and she gets a conflict, which she postpones:
$ svn updateConflict discovered in 'sandwich.txt'.Select: (p) postpone, (df) diff-full, (e) edit, (h)elp for more options : pC sandwich.txtUpdated to revision 2.$ ls -1sandwich.txtsandwich.txt.minesandwich.txt.r1sandwich.txt.r2
At this point, Subversion willnot allow Sally to commit the filesandwich.txt until the three temporary files are removed:
$ svn commit -m "Add a few more things"svn: Commit failed (details follow):svn: Aborting commit: '/home/sally/svn-work/sandwich.txt' remains in conflict
If you've postponed a conflict, you need to resolve the conflict before Subversion will allow you to commit your changes. You'll do this with thesvn resolve command and one of several arguments to the--accept option.
If you want to choose the version of the file that you last checked out before making your edits, choose thebase argument.
If you want to choose the version that contains only your edits, choose themine-full argument.
If you want to choose the version that your most recent update pulled from the server (and thus discarding your edits entirely), choose thetheirs-full argument.
However, if you want to pick and choose from your changes and the changes that your update fetched from the server, merge the conflicted text “by hand” (by examining and editing the conflict markers within the file) and then choose theworking argument.
svn resolve removes the three temporary files and accepts the version of the file that you specified with the--accept option, and Subversion no longer considers the file to be in a state of conflict:
$ svn resolve --accept working sandwich.txtResolved conflicted state of 'sandwich.txt'
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 filesandwich.txt at the same time. Sally commits her changes, and when you go to update your working copy, you get a conflict and you're going to have to editsandwich.txt to resolve the conflict. First, let's take a look at the file:
$ cat sandwich.txtTop piece of breadMayonnaiseLettuceTomatoProvolone<<<<<<< .mineSalamiMortadellaProsciutto=======SauerkrautGrilled Chicken>>>>>>> .r2Creole MustardBottom piece of bread
The strings of less-than signs, equals 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:
<<<<<<< .mineSalamiMortadellaProsciutto=======
The text between the second and third sets of conflict markers is the text from Sally's commit:
=======SauerkrautGrilled 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. 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.[6] Once you've agreed on the changes you will commit, edit your file and remove the conflict markers:
Top piece of breadMayonnaiseLettuceTomatoProvoloneSalamiMortadellaProsciuttoCreole MustardBottom piece of bread
Now usesvn resolve, and you're ready to commit your changes:
$ svn resolve --accept working sandwich.txtResolved conflicted state of 'sandwich.txt'$ svn commit -m "Go ahead and use my sandwich, discarding Sally's edits."
Note thatsvn resolve, unlike most of the other commands we deal with in this chapter, requires that you explicitly list any filenames that you wish to resolve. In any case, you want to be careful and usesvn resolve only 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.
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.
If you get a conflict and decide that you want to throw out your changes, you can runsvn resolve --accept theirs-full and Subversion will discard your edits and remove the temporary files:CONFLICTED-PATH
$ svn updateConflict discovered in 'sandwich.txt'.Select: (p) postpone, (df) diff-full, (e) edit, (h) help for more options: pC sandwich.txtUpdated to revision 2.$ ls sandwich.*sandwich.txt sandwich.txt.mine sandwich.txt.r2 sandwich.txt.r1$ svn resolve --accept theirs-full sandwich.txtResolved conflicted state of 'sandwich.txt'
If you decide that you want to throw out your changes and start your edits again (whether this occurs after a conflict or anytime), just revert your changes:
$ svn revert sandwich.txtReverted 'sandwich.txt'$ ls sandwich.*sandwich.txt
Note that when you revert a conflicted file, you don't have to usesvn resolve.
Finally! Your edits are finished, you've merged all changes from the server, and you're ready to commit your changes to the repository.
Thesvn commit command sends all of your changes to the repository. When you commit a change, you need to supply alog 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 -m "Corrected number of cheese slices."Sending sandwich.txtTransmitting 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 (-F) option:
$ svn commit -F logmsgSending sandwich.txtTransmitting file data .Committed revision 4.
If you fail to specify either the--message or--file option, Subversion will automatically launch your favorite editor (see the information oneditor-cmd inthe section called “Config”) 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, save again, and then abort:
$ svn commitWaiting for Emacs...DoneLog message unchanged or not specified(a)bort, (c)ontinue, (e)dita$
The repository doesn't know or care whether your changes make any sense as a whole; it checks only to make sure nobody else has changed any of the same files that you did when you weren't looking. If somebodyhas done that, the entire commit will fail with a message informing you that one or more of your files are out of date:
$ svn commit -m "Add another rule"Sending rules.txtsvn: Commit failed (details follow):svn: File '/sandwich.txt' is out of date…
(The exact wording of this error message depends on the network protocol and server you're using, but the idea is the same in all cases.)
At this point, you need to runsvn update, deal with any merges or conflicts that result, and attempt your commit again.
That covers the basic work cycle for using Subversion. Subversion offers many other features that you can use to manage your repository and working copy, but most of your day-to-day use of Subversion will involve only the commands that we've discussed so far in this chapter. We will, however, cover a few more commands that you'll use fairly often.
[4]Of course, nothing is ever totally deleted from the repository—just from theHEAD of the repository. You can get back anything you delete by checking out (or updating your working copy to) a revision earlier than the one in which you deleted it. Also seethe section called “Resurrecting Deleted Items”.
[5]And you don't have a WLAN card. Thought you got us, huh?
[6]And if you ask them for it, they may very well ride you out of town on a rail.
You are readingVersion Control with Subversion (for Subversion 1.5), by Ben Collins-Sussman, Brian W. Fitpatrick, and C. Michael Pilato.
This work is licensed under theCreative Commons Attribution License v2.0.
To submit comments, corrections, or other contributions to the text, please visithttp://www.svnbook.com/.