This text is a work in progress—highly subject to change—and may not accurately describe any released version of the Apache™ Subversion® software. Bookmarking or otherwise referring others to this page is probably not such a smart idea. Please visit http://www.svnbook.com/ for stable versions of this book.
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. This involves the use of the svn update command.
Make your changes. The most common changes that you'll make are edits to the contents of your existing files. But sometimes you need to add, remove, copy and move files and directories—the svn add, svn delete, svn copy, and svn move commands handle those sorts of structural changes within the working copy.
Review your changes. The svn status and svn diff commands are critical to reviewing the changes you've made in your working copy.
Fix your mistakes. Nobody's perfect, so as you review your changes, you may spot something that's not quite right. Sometimes the easiest way to fix a mistake is start all over again from scratch. The svn revert command restores a file or directory to its unmodified state.
Resolve any conflicts (merge others' changes). In the time it takes you to make and review your changes, others might have made and published changes, too. You'll want to integrate their changes into your working copy to avoid the potential out-of-dateness scenarios when you attempt to publish your own. Again, the svn update command is the way to do this. If this results in local conflicts, you'll need to resolve those using the svn resolve command.
Publish (commit) your changes. The svn commit command transmits your changes to the repository where, if they are accepted, they create the newest versions of all the things you modified. Now others can see your work, too!
When working on a project that is being modified via multiple working copies, you'll want to update your working copy to receive any changes committed from other working copies since your last update. These might be changes that other members of your project team have made, or they might simply be changes you've made yourself from a different computer. To protect your data, Subversion won't allow you commit new changes to out-of-date files and directories, so it's best to have the latest versions of all your project's files and directories before making new changes of your own.
Use svn update to bring your working copy into sync with the latest revision in the repository:
$ svn update Updating '.': U foo.c U bar.c Updated to revision 2. $
In this case, it appears that someone committed
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.
When the server sends changes to your working copy via
svn 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, run svn help update
or
see svn update (up) in
svn Reference—Subversion Command-Line Client.
Now you can get to work and make changes in your working copy. You can make two kinds of changes to your working copy: file changes and tree 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. Tree changes are different, and involve changes to a directory's structure. Such changes include adding and removing files, renaming files or directories, and copying files or directories to new locations. For tree changes, you use Subversion operations to “schedule” files and directories for 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.
Here is an overview of the five Subversion subcommands that you'll use most often to make tree changes:
svn add FOO
Use this to schedule the file, directory, or
symbolic link FOO
to be added to
the repository. 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 want only to add
FOO
itself, pass the
--depth=empty
option.
svn delete FOO
Use this to schedule the file, directory, or
symbolic link FOO
to be deleted
from the repository. FOO
is
immediately deleted from your working copy.
(Of course, nothing is ever totally deleted from the
repository—just from its HEAD
revision.
You may continue to access the deleted item in previous
revisions).
[6]
svn copy FOO BAR
Create a new item BAR
as a
duplicate of FOO
and automatically
schedule BAR
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 unless you pass the
--parents
option.
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 unless you pass the
--parents
option.
svn mkdir FOO
This command is exactly the same as running
mkdir FOO; svn add FOO
. That is,
a new directory named FOO
is
created and scheduled for addition.
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 compose a more accurate log message (a human-readable description of the committed changes stored alongside those changes in the repository). You may also discover that you've inadvertently changed a file, and that you need to undo that change 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 using the svn status command, and you can dig into the details of those changes by using the svn diff command.
To get an overview of your changes, use the svn status command. You'll probably use svn status more than any other Subversion command.
Tip | |
---|---|
Because the cvs status command's output was so noisy, and because cvs update not only performs an update, but also reports the status of your local changes, most CVS users have grown accustomed to using cvs update to report their changes. In Subversion, the update and status reporting facilities are completely separate. See the section called “Distinction Between Status and Update” for more details. |
If you run svn status
at the top
of your working copy with no additional arguments, it will
detect and report all file and tree changes you've
made.
$ svn status ? scratch.c A stuff/loot A stuff/loot/new.c D stuff/old.c M bar.c $
In its default output mode, svn status prints seven 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. Some of the most common codes that svn status displays are:
? item
The file, directory, or symbolic link
item
is not under version
control.
A item
The file, directory, or symbolic link
item
has been scheduled for
addition into the repository.
C item
The 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 (and weren't
resolved during the update). You must resolve this
conflict before committing your changes to the
repository.
D item
The file, directory, or symbolic link
item
has been scheduled for
deletion from the repository.
M item
The contents of the file item
have been modified.
If you pass a specific path to svn status, you get information about that item alone:
$ svn status stuff/fish.c D stuff/fish.c
svn status also has a
--verbose
(-v
) option,
which will show you the status of every
item in your working copy, even if it has not been
changed:
$ svn status -v 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 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 to svn
status contact the repository—they merely
report what is known about the working copy items based on
the records stored in the working copy administrative area
and on the timestamps and contents of modified files. But
sometimes it is useful to see which of the items in your
working copy have been modified in the repository since the
last time you updated your working copy. For
this, svn status offers the
--show-updates
(-u
)
option, which contacts the repository and adds information
about items that are out of date:
$ svn status -u -v 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 in the previous example 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—because one of those items is also
one that you have locally modified (the
file README
), you'll need to update and
get the server's changes for that file before you commit, or
the repository will reject your commit for being out of
date. We discuss this in more detail 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 of svn status and its output,
run svn help status
or see
svn status (stat, st) in
svn Reference—Subversion Command-Line Client.
Another way to examine your changes is with the
svn diff command, which displays
differences in file content. When you run svn
diff
at the top of your working copy with no
arguments, Subversion will print the changes you've made to
human-readable files in your working copy. It displays
those changes in unified diff format,
a format which describes changes as “hunks”
(or “snippets”) of a file's content where each
line of text is prefixed with a single-character code: a
space, which means the line was unchanged; a minus sign
(-
), which means the line was removed
from the file; or a plus sign (+
), which
means the line was added to the file. In the context
of svn diff, those minus-sign- and
plus-sign-prefixed lines show how the lines looked before
and after your modifications, respectively.
Here's an example:
$ 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 its pristine text-base. Files scheduled for addition are displayed as files in which every line was added; files scheduled for deletion are displayed as if every line was removed from those files. The output from svn diff is somewhat compatible with the patch program—more so with the svn patch subcommand introduced in Subversion 1.7. Patch processing commands such as these read and apply patch files (or “patches”), which are files that describe differences made to one or more files. Because of this, you can share the changes you've made in your working copy with someone else without first committing those changes by creating a patch file from the redirected output of svn diff:
$ svn diff > patchfile $
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 additional flags
that it needs via the --extensions
(-x
) option. For example, you might want
Subversion to defer its difference calculation and display
to the GNU diff program, asking that
program to print local modifications made to the
file foo.c
in context diff format
(another flavor of difference format) while ignoring changes
made only to the case of the letters used in the file's
contents:
$ svn diff --diff-cmd /usr/bin/diff -x "-i" foo.c … $
Suppose while viewing the output of svn
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. You could edit the
file again and unmake all those changes. You could try to
find a copy of how the file looked before you changed it, and
then copy its contents atop your modified version. You
could attempt to apply those changes to the file again in
reverse using svn patch --reverse-diff
or using your operating system's patch -R
.
And there are probably other approaches you could take.
Fortunately in Subversion, undoing your work and starting over from scratch doesn't require such acrobatics. Just use the svn revert command:
$ svn status README M README $ svn revert README Reverted 'README' $ svn status README $
In this example, Subversion has reverted the file to its premodified state by overwriting it with the pristine version of the file cached in the text-base area. But note that svn revert can undo any scheduled operation—for example, you might decide that you don't want to add a new file after all:
$ svn status new-file.txt ? new-file.txt $ svn add new-file.txt A new-file.txt $ svn revert new-file.txt Reverted 'new-file.txt' $ svn status new-file.txt ? new-file.txt $
Or perhaps you mistakenly removed a file from version control:
$ svn status README $ svn delete README D README $ svn revert README Reverted 'README' $ svn status README $
The svn revert command offers salvation for imperfect people. It can save you huge amounts of time and energy that would otherwise be spent manually unmaking changes or, worse, disposing of your working copy and checking out a fresh one just to have a clean slate to work with again.
We've already seen how svn status
-u
can predict conflicts, but dealing with those
conflicts is still something that remains to be done.
Conflicts can occur any time you attempt to merge or integrate
(in a very general sense) changes from the repository into
your working copy. By now you know that svn
update creates exactly that sort of
scenario—that command's very purpose is to bring your
working copy up to date with the repository by merging all the
changes made since your last update into your working copy.
So how does Subversion report these conflicts to you, and how
do you deal with them?
Suppose you run svn update
and you
see this sort of interesting output:
$ svn update Updating '.': U INSTALL G README Conflict discovered in 'bar.c'. Select: (p) postpone, (df) show diff, (e) edit file, (m) merge, (mc) my side of conflict, (tc) their side of conflict, (s) show all options:
The U
(which stands for
“Updated”) and G
(for “merGed”) codes are no cause for concern;
those files cleanly absorbed changes from the repository. A
file marked with U
contains
no local changes but was updated with changes from the
repository. One marked with
G
had local changes to begin
with, but the changes coming from the repository didn't
conflict with those local changes.
It's the next few lines which are interesting. First,
Subversion reports to you that in its attempt to merge
outstanding server changes into the
file bar.c
, it has detected that some of
those changes clash with local modifications you've made to
that file in your working copy but have not yet committed.
Perhaps someone has changed the same line of text you also
changed. Whatever the reason, Subversion instantly flags this
file as being in a state of conflict. It then asks you what
you want to do about the problem, allowing you to
interactively choose an action to take toward resolving the
conflict. The most commonly used options are displayed, but
you can see all of the options by
typing s
:
… Select: (p) postpone, (df) show diff, (e) edit file, (m) merge, (mc) my side of conflict, (tc) their side of conflict, (s) show all options: s (e) - change merged file in an editor [edit] (df) - show all changes made to merged file (r) - accept merged version of file (dc) - show all conflicts (ignoring merged version) (mc) - accept my version for all conflicts (same) [mine-conflict] (tc) - accept their version for all conflicts (same) [theirs-conflict] (mf) - accept my version of entire file (even non-conflicts) [mine-full] (tf) - accept their version of entire file (same) [theirs-full] (m) - use internal merge tool to resolve conflict (l) - launch external tool to resolve conflict [launch] (p) - mark the conflict to be resolved later [postpone] (q) - postpone all remaining conflicts (s) - show this list (also 'h', '?') Words in square brackets are the corresponding --accept option arguments. Select: (p) postpone, (df) show diff, (e) edit file, (m) merge, (mc) my side of conflict, (tc) their side of conflict, (s) show all options:
Let's briefly review each of these options before we go into detail on what each option means.
(e) edit [edit]
Open the file in conflict with your favorite editor,
as set in the environment variable
EDITOR
.
(df) diff-full
Display the differences between the base revision and the conflicted file itself in unified diff format.
(r) resolved
After editing a file, tell svn that you've resolved the conflicts in the file and that it should accept the current contents—basically that you've “resolved” the conflict.
(dc) display-conflict
Display all conflicting regions of the file, ignoring changes which were successfully merged.
(mc) mine-conflict [mine-conflict]
Discard any newly received changes from the server which conflict with your local changes to the file under review. However, accept and merge all non-conflicting changes received from the server for that file.
(tc) theirs-conflict [theirs-conflict]
Discard any local changes which conflict with incoming changes from the server for the file under review. However, preserve all non-conflicting local changes to that file.
(mf) mine-full [mine-full]
Discard all newly received changes from the server for the file under review, but preserve all your local changes for that file.
(tf) theirs-full [theirs-full]
Discard all your local changes to the file under review and use only the newly received changes from the server for that file.
(m) merge
Launch an internal file merge tool to perform the conflict resolution. The option is available starting with Subversion 1.8.
(l) launch
Launch an external program to perform the conflict resolution. This requires a bit of preparation beforehand.
(p) postpone [postpone]
Leave the file in a conflicted state for you to resolve after your update is complete.
(s) show all
Show 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. Two of the commands available at the
interactive conflict resolution prompt can assist you here.
The first is the “diff-full” command
(df
), which displays all the local
modifications to the file in question plus any conflict
regions:
… Select: (p) postpone, (df) show diff, (e) edit file, (m) merge, (mc) my side of conflict, (tc) their side of conflict, (s) show all options: df --- .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 (the BASE
revision), the next content line is your change, and the
last content line is the change that was just received from
the server (usually the
HEAD
revision).
The second command is similar to the first, but
the “display-conflict”
(dc
) command shows only the conflict
regions, not all the changes made to the file.
Additionally, this command uses a slightly different display
format for the conflict regions which allows you to more
easily compare the file's contents in those regions as they
would appear in each of three states: original and unedited;
with your local changes applied and the server's conflicting
changes ignored; and with only the server's incoming changes
applied and your local, conflicting changes reverted.
After reviewing the information provided by these commands, you're ready to move on to the next action.
The main way to resolve conflicts interactively is to use an internal file merge tool. The tool asks you what to do with each conflicting change and allows you to selectively merge and edit changes. However, there are several other different ways to resolve conflicts interactively—two of them allow you to selectively merge and edit changes using external editors, the rest of which allow you to simply pick a version of the file and move along. Internal merge tool combines all of the available ways to resolve conflicts.
You've already reviewed the conflicting changes, so it's
now time to resolve the conflicts. The first command that
should help you is the “merge” command
(m
) which is available starting with
Subversion 1.8. The command displays the conflicting
areas and allows you to choose from a number of options to
resolve the conflicts area-by-area:
Select: (p) postpone, (df) show diff, (e) edit file, (m) merge, (mc) my side of conflict, (tc) their side of conflict, (s) show all options: m Merging 'Makefile'. Conflicting section found during merge: (1) their version (at line 24) |(2) your version (at line 24) ------------------------------------------------+------------------------------------------------ top_builddir = /bar |top_builddir = /foo ------------------------------------------------+------------------------------------------------ Select: (1) use their version, (2) use your version, (12) their version first, then yours, (21) your version first, then theirs, (e1) edit their version and use the result, (e2) edit your version and use the result, (eb) edit both versions and use the result, (p) postpone this conflicting section leaving conflict markers, (a) abort file merge and return to main menu:
As you can see, when you use the internal file merge tool, you can cycle through individual conflicting areas in the file and select various resolution options or postpone conflict resolution for selected conflicts.
However, if you wish to use an external editor 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 (configured per the
instructions in the section called “Using External Editors”). 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 “resolved” command
(r
).
Regardless of what your local Unix snob will likely tell
you, editing the file by hand in your favorite text editor
is a somewhat low-tech way of remedying conflicts (see
the section called “Manual conflict resolution” for a
walkthrough). For this reason, Subversion provides
the “launch” resolution command
(l
) to fire up a fancy graphical
merge tool instead (see
the section called “External merge”).
There is also a pair of compromise options
available. The “mine-conflict”
(mc
)
and “theirs-conflict”
(tc
) commands instruct Subversion to
select your local changes or the server's incoming changes,
respectively, as the “winner” for all conflicts
in the file. But, unlike the “mine-full”
and “theirs-full” commands, these commands
preserve both your local changes and changes received from
the server in regions of the file where no conflict was
detected.
Finally, 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 type p
to postpone
resolving a conflict on a file-by-file basis when you run
svn update
. If you know in advance
that you don't want to resolve any conflicts interactively,
you can pass the --non-interactive
option
to svn update, and any file in conflict
will be marked with a C
automatically.
Beginning with Subversion 1.8, an internal file merge tool allows you to postpone conflict resolution for certain conflicts, but resolve other conflicts. Therefore, you can postpone conflict resolution area-by-area, not just on a file-to-file basis.
The C
(for “Conflicted”) 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 a C
during the update and remembers that the file is in a
state of conflict.
If Subversion considers the file to be mergeable, it
places conflict
markers—special strings of text that
delimit the “sides” of the
conflict—into the file to visibly demonstrate the
overlapping areas. (Subversion uses the
svn:mime-type
property to decide whether a
file is capable of contextual, line-based merging. See
the section called “File Content Type”
to learn more.)
For every conflicted file, Subversion places three extra unversioned files in your working copy:
filename.mine
This is the file as it existed in your working
copy before you began the update process. It
contains any local modifications you had made to
the file up to that point. (If Subversion
considers the file to be unmergeable,
the .mine
file isn't created,
since it would be identical to the working
file.)
filename.rOLDREV
This is the file as it existed in the
BASE
revision—that is,
the unmodified revision of the file in your
working copy before you began
the update process—where
OLDREV
is that base
revision number.
filename.rNEWREV
This is the file that your Subversion client
just received from the server via the update of
your working copy, where
NEWREV
corresponds to
the revision number to which you were updating
(HEAD
, unless otherwise
requested).
For example, Sally makes changes to the file
sandwich.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 update Updating '.': Conflict discovered in 'sandwich.txt'. Select: (p) postpone, (df) show diff, (e) edit file, (m) merge, (mc) my side of conflict, (tc) their side of conflict, (s) show all options: p C sandwich.txt Updated to revision 2. Summary of conflicts: Text conflicts: 1 $ ls -1 sandwich.txt sandwich.txt.mine sandwich.txt.r1 sandwich.txt.r2
At this point, Subversion will not
allow Sally to commit the file
sandwich.txt
until the three temporary
files are removed:
$ svn commit -m "Add a few more things" svn: E155015: Commit failed (details follow): svn: E155015: 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 the svn
resolve command. This command accepts
the --accept
option, which allows you
specify your desired approach for resolving the conflict.
Prior to Subversion 1.8, the svn resolve
command required the use of this option.
Subversion now allows you to run the svn
resolve command without that option. When you do
so, Subversion cranks up its interactive conflict resolution
mechanism, which you can read about (if you haven't done so
already) in the previous section,
the section called “Resolving conflict differences interactively”. We'll
take the opportunity in this section, though, to discuss
the use of the --accept
option for
conflict resolution.
The --accept
option to the svn
resolve command instructs Subversion to use one of
its pre-packaged approaches to conflict resolution. If
you want Subversion to resolve the conflict using the
version of the file that you last checked out before making
your edits, use --accept=base
. If you'd
prefer instead to keep the version that contains only your
edits, use --accept=mine-full
. You can also
select the version that your most recent update pulled from
the server (discarding your edits entirely)—that's
done using --accept=theirs-full
. There
are other “canned” resolution types, too. See
--accept
ACTION
in
svn Reference—Subversion Command-Line Client for details.
You aren't limited strictly to all-or-nothing options.
If you want to pick and choose from your changes and the
changes that your update fetched from the server, you can
manually repair the working file, fixing up the conflicted
text “by hand” (by examining and editing the
conflict markers within the file), then tell Subversion to
resolve the conflict by keeping the working file in its
current state by running svn resolve with
the --accept=working
option.
svn resolve removes the three temporary files and accepts the version of the file that you specified. After the command completes successfully—and assuming you didn't interactively choose to postpone resolution, of course—Subversion no longer considers the file to be in a state of conflict:
$ svn resolve --accept working sandwich.txt Resolved conflicted state of 'sandwich.txt'
Manually resolving conflicts 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 you're going to have to edit
sandwich.txt
to resolve the conflict.
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, 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:
<<<<<<< .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. 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.[7] Once you've agreed on the changes you will commit, edit your file and remove the conflict markers:
Top piece of bread Mayonnaise Lettuce Tomato Provolone Salami Mortadella Prosciutto Creole Mustard Bottom piece of bread
Now use svn resolve, and you're ready to commit your changes:
$ svn resolve --accept working sandwich.txt Resolved conflicted state of 'sandwich.txt' $ svn commit -m "Go ahead and use my sandwich, discarding Sally's edits."
Naturally, you want to be careful that when using svn resolve you don't tell Subversion that you've resolved a conflict when you truly haven't. 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 run svn
resolve --accept theirs-full
and
Subversion will discard your edits and remove the temporary
files:CONFLICTED-PATH
$ svn update Updating '.': Conflict discovered in 'sandwich.txt'. Select: (p) postpone, (df) show diff, (e) edit file, (m) merge, (mc) my side of conflict, (tc) their side of conflict, (s) show all options: p C sandwich.txt Updated to revision 2. Summary of conflicts: Text conflicts: 1 $ ls sandwich.* sandwich.txt sandwich.txt.mine sandwich.txt.r2 sandwich.txt.r1 $ svn resolve --accept theirs-full sandwich.txt Resolved 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.txt Reverted 'sandwich.txt' $ ls sandwich.* sandwich.txt $
Note that when you revert a conflicted file, you don't have to use svn 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.
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
(-m
) option:
$ svn commit -m "Corrected number of cheese slices." Sending sandwich.txt Transmitting file data . Committed revision 3.
However, if you've been composing your log message in some
other text file as you work, you may want to tell Subversion
to get the message from that file by passing its filename as
the value of the --file
(-F
)
option:
$ svn commit -F logmsg Sending sandwich.txt Transmitting file data . Committed revision 4.
If you fail to specify either the
--message
(-m
)
or --file
(-F
) option,
Subversion will automatically launch your favorite editor (see
the information on editor-cmd
in
the section called “General configuration”) for
composing a log message.
Tip | |
---|---|
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 all the text, save again, and then abort: $ 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 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 somebody has 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.txt Transmitting file data . svn: E155011: Commit failed (details follow): svn: E155011: File '/home/sally/svn-work/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 run svn
update
, deal with any merges or conflicts that
result, and then 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.
[6] Should you desire to resurrect the item
so that it is again present in HEAD
, see
the section called “Resurrecting Deleted Items”.
[7] And if you ask them for it, they may very well ride you out of town on a rail.