2.4. The Repository Life Cycle

Now that you have your repository, you need to keep it up to date. Any changes you make to your local copy of the code need to be registered back to the Subversion server before other developers can see it and the change can be assigned a revision tag.

2.4.1. Committing Normal Code Changes

Most of the time, the changes that you make to your code will simply involve changing text within an existing file. As you've seen, the svn commit command causes all of the changes in your local copy to be sent to the server. Subversion requires you to add a short message to the commit, describing the change by using the -m flag, as in svn commit -m "I fixed that really hairy bug. Hooray for me". If you don't include a descriptive message, Subversion will try to launch your system's default editor for you to type one in.

If you've lost track of the revisions you've made since your last commit, you can get a handy list by using the svn status command as follows:

$ svn status
?      edge_update.sh
?      soupsonline.tmproj
M      test/unit/ingredient_test.rb
M      test/functional/ingredients_controller_test.rb
M      test/functional/recipes_controller_test.rb
M      app/controllers/ingredients_controller.rb
M      app/views/recipes/show.html.erb
?      app/views/ingredients/remote_update.html.erb
M      app/views/ingredients/remote_edit.html.erb
?      db/schema.rb
X      vendor/rails
?      public/images/spacer.gif
?      public/images/img10.gif
?      public/images/img01.gif
?      public/images/img11.gif
?      public/images/img02.gif
?      public/images/img12.gif
?      public/images/img04.gif
?      public/images/img05.gif
?      public/images/img06.gif
?      public/images/img07.gif
?      public/images/img08.gif
?      public/images/img09.gif
?      public/images/img03.jpg
M      public/stylesheets/scaffold.css

Each file is prefixed by a character that describes that file's status. In this case, you have M, meaning the file has been modified; X, meaning the directory is part of an external definition; and ?, meaning the file is not under version control. You might also see A, D, or C, which mean the item is scheduled to be added, scheduled to be deleted, or currently in a conflict state, respectively.

The great thing about the svn status command is that all the data needed to run it is local to your copy — you don't have to be connected to the network to run the default version of the command. However, when you are connected to the network, you can get extra information by using the --show-updates option. When selected, Subversion connects to the server and puts an asterisk next to any file that has a more recent change on the server. Remember, if there is a more recent change, Subversion will not allow you to commit unless you update and resolve any conflicts.

2.4.2. Updates and Conflicts

You retrieve recent changes using the svn update command, which brings your working copy up-to-date with respect to the central repository. The output of the command is a list of all the files changed, each prefixed by a character that indicates what kind of change has been made.

The most common change character is U, meaning that there has been an update to a file that has not changed on the local copy. Other change types that do not affect local code are A and D, indicating that a file has been added or deleted.

If a file that you have changed locally has also changed on the repository, then you have one of two change types. If the two changes are in different parts of the file and do not affect each other, then the code is G for "merged." This means that Subversion has managed to integrate the two sets of changes on its own and the file should be in a valid state. But it's usually a good idea to run your test suite, just to be on the safe side.

If both you and somebody else on your project have made incompatible changes to the same part of a file, then the code is C, for "conflict." When Subversion detects a conflict, you will be prevented from committing your code back to the repository until you resolve the conflict.

To help resolve the conflict, Subversion does a couple of things that allow you to see the problem clearly. Subversion changes the file under conflict to mark where the conflict occurs. In addition, Subversion creates three complete alternate versions of the file, each with a new extension. They are as follows:

  • .r<BASE REV #> is the file as it was before you started messing with it. The <BASE REV #> is set to the number of the Subversion revision that you started with. For example, if you were conflicted over the recipe_controller.rb file and your previous update was from revision 100, then this version would be recipe_controller.rb.r100.

  • .r<HEAD REV #> is the file as it currently stands in the repository. The <HEAD REV #> is the most recent revision number, and will be the higher of the two numbers. Continuing the example from the previous bullet, this file might be recipe_controller.rb.r103.

  • .mine is the file as you lovingly edited it (before Subversion gunked it up with markers to show the conflict).

These files give you three quick-and-easy ways to resolve the conflict. If you're convinced that your version contains the wisdom of the angels, and your coworker is deluded, take the .mine file, and copy it over the original file. If you think that your coworker is smarter than you, take the .rHEAD version and copy that one over the original. If you want to chuck the whole thing and start over, take the rBASE version.

If none of these options really fits, then there's no getting around it — you'll have to look at the original file with its markers. The file will look something like this:

def create
    @recipe = Recipe.new(params[:recipe])
    respond_to do |format|
      if @recipe.save
<<<<<<< .mine
        flash[:notice] = 'Recipe was spectacularly created.'
=======
        flash[:notice] = 'Recipe was wonderfully created.'
>>>>>>> .r103
        format.html { redirect_to(@recipe) }
        format.xml  { render :xml => @recipe,
            :status => :created, :location => @recipe }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @recipe.errors,
            :status => :unprocessable_entity }
      end
    end
  end

In this case, you and your codeveloper are fighting over the adjective used to describe a successful recipe creation. (Well, I've seen bigger arguments over smaller things.)

Subversion alerts you to the location of the change by the three-part delimiter. The >> signs at the start indicate the beginning of the conflicted section, and the .mine at the end of that line tells you which revision is responsible for all the code between that line and the === line. All the code between the === line and the >>> line comes from the .r103 version of the file.

Now that you can see the two versions of the file side-by-side (or at least top-to-bottom), edit the file as needed to get it to the actual state you want. Be sure to remove the delimiters — the Ruby interpreter isn't going to like it if those stay in.

When the file is the way you want it (run your automated tests to confirm it), you tell Subversion that the conflict has been resolved with the command svn resolved <filename>, where the filename is the path to the file you just finished messing with. Subversion will note the resolution and delete the temporary files for you (be careful — you can't get them back once they are gone). When all conflicts are resolved, your commit will be allowed to proceed.

2.4.3. File-Level Changes

Subversion is not content only knowing about the changes you make within existing files. Subversion also wants to know about changes you make to the file structure itself.

When you add a new file to your Rails project, you must remember to register the change with Subversion using svn add <PATH>. The path can be a filename or a directory — if it's a directory, you get the contents of that directory and all its subdirectories added. The path can contain wildcard characters, which are interpreted normally. By itself, the add command updates only your local copy. The change is not passed to the central repository until your next commit.

Many of the files you add to Rails will be via the generate script. No matter what kind of thing you are generating, the script can always take the --svn option, which causes any file created by the generator to be automatically added to Subversion control. Again, a commit is needed for the change to be visible to the central repository.

To create an entire directory, use svn mkdir <PATH>. To remove a file, you use the command svn delete <PATH>. You can also copy and move files using svn copy <FROM> <TO> and svn move <FROM> <TO>. A move is identical to performing a copy followed by a deletion. At the risk of repeating myself, none of these takes full effect until the next commit.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.21.159.82