• No se han encontrado resultados

Capítulo I: Marco teórico

1.3 El emprendedor

1.3.3 El emprendedor académico

Sometimes, you need to look at just one single file from the repository. Unfortunately,svn checkoutdoesn’t allow you to specify just a single file, only directories. Getting single files is where thesvn catcommand comes in handy. When run,svn catcontacts the repository and downloads just a single file, which it outputs to the terminal. In many cases, you will then want to redirect (using a>)svn cat’s output into a file.

“svnbook” — 2005/4/14 — 14:55 — page 76 — #97

i i

76 Chapter 5 Working with a Working Copy

5.5

Changing the Working Copy Target

Inside a working copy, Subversion makes it fairly simple to move files and directories between different revisions, and even different repositories. For the most part, movement between revisions is done using the svn updatecommand. Running svn update, by default, updates a file or directory in a working copy to the latest revision in the repository. However, if you supply a--revision(-r) option when the command is run, Subversion instead updates the file in the working copy to that revision, even if it is prior to the current revision in the repository.

$ svn update --revision 1773 foo.c U foo.c

In addition to moving between revisions withsvn update, you can also use thesvn switch command to change a working copy’s URL. This allows you, for instance, to switch a directory to a branch. As an example, the following svn switch command switches thetrunkdirectory in the working copy to instead represent themybranchbranch in thebranchesdirectory.

$ svn switch http://svn.example.com/repos/branches/mybranch trunk/ U foo.c

A foo.h U bar.c U Makefile D README.txt

The preceding use ofsvn switchrequires that the given URL be in the same reposi- tory as the working copy. You can, however, also usesvn switchto completely change the repository that a working copy looks to. This is done by running the command with the--relocateoption, which goes through a working copy and changes the base URL of every file or directory that matches the given original base (think find and replace). For example, the following example shows a URL relocation of the working copytrunkdi- rectory (and its contents) fromexample.comtoexample.net.

$ svn switch --relocate http://svn.example.com/repos http://svn.example¬

.net/repos trunk/

5.6

Resolving Conflicts

Whenever Subversion encounters changes from two different sources, it attempts to per- form an automatic merge. If Subversion fails to successfully merge, a conflict occurs. This can happen in a couple of cases. The first is the instance where the changes occur in the same location in the two versions of the file. Because Subversion doesn’t know anything about the context of a file, it has no way to merge colliding changes, and must declare a conflict. The other case where a conflict occurs is the case where a binary file is being

5.6 Resolving Conflicts 77

merged. Binary files are usually very intolerant to minor changes performed by something that doesn’t understand the file, which means that using Subversion’s textual merge on a binary file would more often than not result in a file that was unreadable. Because Sub- version doesn’t have any means to merge a binary file, it always declares a conflict when changes from two different sources must be merged.

When a conflict does occur, Subversion creates several different copies of the original file in your home directory. Each copy of the file is a different version of the file from one of several different revisions. The files are all named with an extension telling where the file came from, appended onto the original name of the file. For example, if the file comes from revision 52 of the filefoo.h, it will be namedfoo.h.r52. If the version of the file is the local working copy version, it will have.mineappended. If the conflict occurs as the result of a merge, the righthand and lefthand files from the merge will be named with

.rightand.left, respectively. In total, the versions of the file that Subversion will create in the case of a conflict consist of the local working copy version of the file with all local modifications, a pristine copy of the local version with no local modifications, and any remote versions of the file that are involved in the conflict.

If the conflicted file is a text file (i.e., not binary), Subversion also modifies the original version of the file (in the working copy) so that it contains both versions of any conflicted sections inline. The conflicted sections are placed, one after the other, with a separator between them (consisting of=signs). Each version is also labeled with its source. The top version shows its source at the beginning of the section, and the bottom source ends with a source label. The labels are denoted with<s and>s respectively, as you can see in the following example.

The Fox: A poem The quick brown fox <<<<<<< .mine

with a javelin, leaped =======

jumped over >>>>>>> .r378 the lazy dog

The work of resolving the conflict is left to you to perform by hand. When you are done, the final, resolved version of the file should reside in your working copy under the original name of the file being resolved (if the file isbar.txt, the resolved version should bebar.txt). You can accomplish this either by editing the original file or by overwriting it with another file—such as one of the versions of the file that Subversion generated in response to the conflict.

While a file is in a conflicted state, Subversion doesn’t allow you to commit the file. If you try, it throws an error and the commit fails. To be able to commit again, you need to tell Subversion when you have finished resolving a conflict. This is done with thesvn

“svnbook” — 2005/4/14 — 14:55 — page 78 — #99

i i

78 Chapter 5 Working with a Working Copy

resolvedcommand, which removes all of the extra files created by Subversion when the conflict was declared (leaving only the originally named version of the file) and removes the block on committing the file. It does not in any way modify the originally named file. As an example, the following shows the complete process you might go through when resolving a conflict during an update. In this case, the version of the file in revision 75 is the correct one to use; it’s moved to replacebar.c.

$ svn update C bar.c $ ls

bar.c bar.c.mine bar.c.r75 $ mv bar.c.r75 bar.c

$ svn resolved

Resolved conflicted state of 'bar.c' $ ls

bar.c

5.7

Branching, Tagging, and Merging

As I explained in earlier chapters, most version control systems allow you to create branches and tags from the main trunk of your repository. Tags allow you to mark specific points in your development (such as releases) for later referral, and branches allow you to split the development of your repository and continue development in parallel on a secondary path. Unlike many other version control systems, Subversion doesn’t actually have a built- in concept of branches or tags. Instead, it just uses cheap server-side copies that preserve history, while not taking up any additional space. Subversion just marks the location of the copied file or directory and notes where it came from. It then allows you to merge the changes from a "branch" back into the main trunk of the repository at a later date. Although the current implementation of Subversion’s copy-merge system does pose the occasional problem—for instance, you can quickly lose track of a file’s full merge/branch history if it becomes more than trivially complex—the flexibility of the paradigm more than makes up for its shortcomings in most cases.

5.7.1

Creating a Branch or Tag

Creating a branch or tag in Subversion is trivially easy. All you need to do is runsvn copy

on the file or directory that you want to branch/tag. Generally, your repository will be set up with one or more directories namedbranchesandtags, which will be where you want to place copies that are conceptually branches or tags. This is a convention, however, and is in no way enforced by Subversion. As far as Subversion is concerned, directories named

branchesortagsare identical to any other directories.

A typical repository layout is to have three top-level directories in the repository, named

trunk,branches, andtags. Thetrunkdirectory contains the main development branch of the repository, and all branches and tags are created by putting copies in their respective

5.7 Branching, Tagging, and Merging 79

directories. By separating the three directories at the top level, you can then check out only thetrunkdirectory, and deal withbranchesandtagsonly in the repository most of the time. When you need to use or edit parts of the repository that are in branches, you can use

svn switchto swap them into your working copy of thetrunkdirectory.

Creating a Branch/Tag in the Repository

The most efficient way to branch or tag a part of the repository is usually to perform the copy entirely in the remote repository. When Subversion performs a copy in the repository, it doesn’t make a copy of the data, but instead just points the copy back to the data from the original. This allows copies of any sized file to occur in a constant amount of time, be it five kilobytes or five hundred megabytes. On the other hand, if the copy is performed in the local working copy, the repository-side copy still occurs in constant time, but you also make a copy of the data in the working copy, which is proportional to the amount of data to be copied.

A repository-only copy is performed usingsvn copywith repository URLs for both source and destination. When the command is run, Subversion performs an immediate commit, which means that it opens an editor to allow you to enter a log message if you don’t supply one on the command line. As an example, the following command shows how you might create a branch of your entire trunk in a typical repository.

$ svn cp --message "Created a new branch" http://svn.example.com/repos/¬

trunk http://svn.example.com/repos/branches/mybranch Committed revision 2353.