Join 3,436 readers in helping fund MetaFilter (Hide)


Help me understand SVN
June 13, 2006 7:47 PM   Subscribe

Help me understand SVN

I'm working for the first time in a job where we have source control.

In the old days I would just upload and hope for the best, or maybe if I was feeling especially careful, take a backup of the file then upload and hope for the best.

Now I follow what is to me an obscure and tedious process using Tortoise.
  1. I "switch to Trunk view" on the PC *
  2. I "Commit" the folder I'm working in *
  3. I "switch to Production view" *
  4. I "Merge" from Production to Trunk (HEAD) *
  5. I "Commit" again *
I have marked with an asterisk the bits of that process I don't understand. Various dialogs come up, I click on OK, but I'm just a trained monkey at this point.

I think I understand the big picture, that is, the SVN system will keep, and allow us to roll back to, earlier versions, that kind of thing. But what actually is happening?

And it appears I followed my set of trained-monkey steps on a folder and accidentally reverted someone else's code to a previous version. How did I do that? And more to the point, isn't the whole point of these things that I should have got an error message saying "hey, that file's newer on the server than on your PC"?

Before I actually had to use one, I imagined SVN and CVS systems as being some kind of magical smart FTP -- I would upload a file and it would just "know" that it should back up the old one, warn if it had been updated since I last downloaded it, or even merge their changes and mine. Apparently it's not that simple!

Anyone who can give me a mental picture of what I'm actually doing when I follow these steps, TIA.
posted by AmbroseChapel to Computers & Internet (18 answers total) 5 users marked this as a favorite
 
The Subversion Book is a good starting place.
posted by kcm at 8:01 PM on June 13, 2006


Which is right here.
posted by kcm at 8:02 PM on June 13, 2006


SVN is actually easier than you think. In some ways it's shame you can't do this from the prompt as it'd benefit you to a greater degree in the long run. I'm going to give you a quick run down, but you should know about the SVN book that's online and free too. I usually do this from a prompt, so I'm going to talk in generalities and hopefully you can fill in the blanks.

1. The "trunk" is the root of the source code. This is where everything is stored. You'll never have to deal with this aside from the initial import. The initial import is as easy as creating a folder, right click, and pick "SVN Import" (or something to that effect). Type the address of the trunk in, it should be something like this:

svn:///svn_repos/path/to/trunk/

Add a dot after the path -- the dot says "dump the files from the trunk DIRECTLY into my folder. Confirm this, and watch the files download.

2. When you make changes to your code, Tortoise will show little red "x"'s on the file and folder icons (this much I know for certain about Tortoise). You just need to right click these things, select "Commit". You might be able to do this on the root directory for your local copy of the project -- or perhaps you have to do it for every file. After you do this, you'll be asked to be write a short message. Be descriptive, but terse!

3. I'm not entirely sure what "production view" means.

4. Again, I'm uncertain of this -- perhaps the aforementioned SVN book will be of use?

5. See #2

I hope this helps a bit.
posted by BioCSnerd at 8:03 PM on June 13, 2006


This chapter looks like a good place to start.
posted by flabdablet at 8:26 PM on June 13, 2006


(really long)

The step I don't understand is #4. I don't understand why you would merge from Production to the Trunk. Is anyone ever committing changes directly into the Production branch?

Basically, Subversion is a repository with a hierarchical structure. Typically, it's set up into projects with useful names, under which you have three subdirectories: trunk, branches, and tags. Under the trunk is the main line of your development, also known as the HEAD. Under the branches folder are any branches you may have created at some point during the development process, and under tags are any tagged revisions (which shouldn't be changed, because if they are they're really branches).

As for switching views, I'm not quite sure what you mean by that. You shouldn't be using Tortoise to switch your repository between URLs except under highly exceptional circumstances. Usually, people have separate copies of the same project on their hard drive simultaneously, one for each branch (or trunk) they're working on. You just need to make sure you keep track of which is which, but Tortoise will keep track for you, too, and you can always find out by checking the file properties.


When you check out from the repository, you usually check out below the trunk, branches, or tags level. Typically, you would check out just the trunk of one project, or one branch, at a time. You can have multiple branches, or the trunk and a branch, checked out on your hard drive to different places, because Subversion creates special directories and files that tie each checked out "sandbox" to a specific URL in the repository.

When you commit changes to your sandbox, you create a new revision of the repository (Subversion, unlike CVS, has "atomic" commits, meaning all the files you commit at a time are part of the same changeset). But your changes are only to the parts of the repository that your sandbox is tied to, so if you want those changes to be made to a separate version of the same project, you have to do a merge.

When you merge, you're making changes to one location of a project based on the differences between its current version and a different location. That is, if you make changes to the trunk, and you've tested those changes, and you want those changes to be on the production branch, you need to merge them "up" to the branch. Merging, mind you, only changes the files in your sandbox, so that you can resolve conflicts and such, and then you commit those changes just as you would any others. Merging doesn't care which version is newer, because it depends on you to tell it which version's changes you are merging from and which you're merging to.

This is why I don't understand step #4. If you have changes on the trunk that need to be in a branch, you need to merge up to the branch, not down to the trunk.
posted by cerebus19 at 8:26 PM on June 13, 2006


That's not my usual tortoise workflow.

I check out the code to some folder. then whenever I have changes, I "update" my working copy with the version in the repository ("update" in the right-click menu for the folder). this will tell me if someone else has changed it in the time i was working, and will let me manage the merge more directly.

Then I commit, and its done.

I think the thing you are not doing is the initial "checking out" the code, but are assuming mode-less operation (assuming Tortoise is forgetting everything after each operation, which is wrong). TortoiseSVN is an "explorer.exe" mod which takes care of all the usual version-control grind that you seem to be referring to. Let the tool manage things!
posted by clord at 8:29 PM on June 13, 2006


It sounds like you are dealing with a development version (the trunk) and a branch used for your production environment. The general idea is that the development version is used to create and test new code. Once it's known to be stable, you can merge the changes that you specifically want to keep into the production branch.

This allows you to develop new code on the trunk, and patch bugs as you go along. If one of those bugs that you patch also needs to be patched on the production environment, then you switch to the production branch and merge those changes into it.

Merging tends to confuse people. Merges should only happen on your local machine, and not on the server. So, before you do a commit, you should do an update first, and make sure that no one has made changes to the files that you've been working on . If changes have been made, tortoise will do it's best to combine those changes with the ones that you've made automagically.

Also, it's super helpful if you leave comments on each commit that you do. That way you can always look at the history and see what's been done.

Be patient, once you get used to SVN, it'll be easy and natural. It's super handy once you get used to it, and it's really a lifesaver.
posted by tumble at 8:30 PM on June 13, 2006


Are you sure you don't have step 4 backwards? In my mind, you should be merging your changes from trunk into production (after you've verified that you changes work and don't break anything).

I'm guessing that you overwrote your coworker's file during the merge process. Suppose I checkout a file at revision 60 (abbr. r60) and make some changes. If I'm the only one working on the file and I commit it right away it becomes r61 and nothing interesting happens.

But suppose someone else (your coworker) also had r60 checked out and he committed his changes first. When you commit, subversion notices that you're trying to overwrite a newer file in the repository than the one you checked out. This is called a conflict. The process of resolving a conflict is called merging. You're presented with an application that shows the repository version (say, r61), your version (a modified r60), and the version you checked out originally (r60, the last common version between the previous two). It's your job to look at the changes and intelligently merge it all together. After that, you tell subversion to commit your merged copy into the repository (and it becomes, say, r62).

My guess is that you didn't look at the changes, told subversion to blindly apply your file over the one in the repository, and your co-worker lost his work. Next time you get a conflict, take a look at what's actually changed and merge it into the file version.

Thinking of subversion/CVS as a "smart FTP" is basically right. You've just failed to consider the question "what happens if two people work on the same file at the same time?"

Just a small warning about my example: I used a continuous set of revision numbers for the file. The truth is that the revision number is for the entire repository (opposed to simply for each file) and it advances with each checkin. So the revision numbers on your files won't be continuous -- they will most likely have gaps -- but it will always be monotonic.
posted by sbutler at 8:31 PM on June 13, 2006


You'll have to describe exactly how you "switch to production view". That's a concept not inherent to either Tortoise or SVN, so it must be something else. My guess is a branch switch?

I set up the subversion setup at work, and here's how ours is set up, with some explanation. I THINK it's similar to yours:

We have a trunk, which we generally check out as c:\src. This is what we use for main development. Pretty much all the work we do is on the trunk, first. So, we edit files and such, and then use tortoise to commit them.

We also have several branches, for the various Production versions of our code. We typically have it checked out as c:
fix. If we made a change on the trunk, and we want it to get on the branch, you have to MERGE it. I'm guessing this is where the confusion came in.

A typical method for merging to the branch is to right click on the root of the branch and select merge. The single most confusing part of tortoise is this dialog. The tricky bit is that there are THREE things involved.

First, there's the branch that you're merging things to. This is what you right clicked on.
Second, there is the START of the branch that you're merging FROM. This is the top box.
Third, there is the END of the branch you are merging FROM, which is the middle box.

An easy way to merge correctly is to enter the location where you wish to merge from in the top box. The location you pick should be at the same level as what you clicked on. So, in our case, if I right clicked on C:\fix and hit merge, in the box I'm going to select svn://servername/trunk as the url. In the middle box, click the box saying they should be the same server. Then, hit the "revision" button in the upper box. Select the revision or revisions that you wish to merge and hit ok. It will enter in the revision numbers for you. Then, hit Ok to do the merge. Also, the dry run button will help you. Press it and see if it did what you expeected. If it modified the wrong files, you probably set the merge dialog up incorrectly

To help people remember, the important thing about the merge dialog is that what it does is it finds the DIFFERENCE between the top two things, and APPLIES that difference to the third thing. My guess as to how you messed up the source code is that you inverted the first and second box. The top box needs to be the revision BEFORE the change you merge, and the middle box should be the revision OF the change you made.

If you have any more specific questions or want more clarification, feel free to ask them. I've spent quite a lot of time explaining SVN to my coworkers :)
posted by JZig at 8:38 PM on June 13, 2006


Subversion has a command line interface; you may find it easier to understand what's going on.

Subversion differs from CVS in that both your changes and the original version are stored locally. Other than commit and log, subversion doesn't have to talk to the repository.

Both CVS and Subversion are not check-out based source control system, as you seem to imply in your comment about a "magical smart FTP". You're not (as in, say, PowerBuilder) checking out one file to make changes in it, and others developers are not prevented form working on the file you've checked out. Instead, both systems will attempt to merge changes locally; in both CVS and svn, if the change cannot me automatically merged, you'll be called on to manually resolve the merge. (And don't worry about this, manually resolving just means, for the most part, choosing one of two alternates for a section of a source file.)

But both do much of what you want in a magical system. One thing, however, to keep in mind: always do an update before you do a commit. Merging is done locally (so that it can, if need be, be manually resolved), not at the repository.

In your explanation of what you're doing, '2. I "Commit" the folder I'm working in *" seems awfully suspicious. You should be doing a commit only after a) you've done an update, to capture any changes made by other developers, and b) when you mean for your version of that file to become the new HEAD version. I think #2 should be an update (which updates your local version, by default to HEAD.)

This is likely how you reverted the other developer's code; he'd committed his new version, you had the old version, and rather than updating to the new, you committed the old, overwriting his changes. (This is no big deal; his version is still in the subversion db, and he or anyone can update to that version, and then commit it.)

When you commit a file, you're making your version everybody's "base" version.

I think Production's not a "view", it's a branch. Basically, your taking what's in the "Production" branch and back-merging it to trunk.

While subversion takes a bit to get used to, it's a joy to have, mostly because it allows you to play with new changes and to not worry if you make a mistake. again, your overwriting is no big deal, precisely because you're using subversion. It wastes a little time, but it does not lasting harm.

You definitely want an RCS, CVS is good too, but subversion is much more friendly than CVS. I even use svn on my personal, non-collaborative work; it makes finding and reverting changes much simpler.
posted by orthogonality at 8:38 PM on June 13, 2006


I mentioned the use of the client side, but here is some clarification on the SVN side of things.

In SVN, the repository should be structured something like this:
/branches
/trunk
/releases
The team works on trunk. Each person operates according to the workflow I mention. Occasionally you make a release, so the repo admin will do a copy of the trunk to a folder, like /releases/v1.0.234. People keep working on trunk.

For bigger projects, of if you want to explore a new feature or start working on version 2 without affecting main-line development, you branch to something like /branches/v2.0 and then proceed working from that. If the team decides they like the results of the branch, you can merge the branch back into the mainline trunk. You can also merge bug-fixes from the trunk into the branch.

Bigger projects typically take to this idea to the extreme, and keep the trunk in a constant state of "goodness" and only merge changes from branches when they are verified and working. Each sub-team develops the branches, and the testing/integration people keep the trunk updated. This is a key concept of version control in general.
posted by clord at 8:40 PM on June 13, 2006


PS. You can do things both ways. You can merge to trunk, or merge to branches. I've seen it done both ways. I personally prefer merging branch work to trunk, and then tagging the trunk with release version numbers.
posted by clord at 8:43 PM on June 13, 2006


Um, some people posting are just causing confusion (sorry guys - if you don't know what 'svn switch' does you are just confusing poor Ambrose).

Two specific things:
* There is only one switch concept in svn, the branch switch, so I'm not sure why people are confused, or if they are, why they're answering. ;)

* A switch is a superset of update, so you don't *need* to do an update, but you should be aware of what branch you have checked out (see the bottom where I suggest a Step 6 and a Step 0).

A couple basic points before I go into each step:

* svn counts revisions globally. Every change that's committed will increment the revision. This is different from CVS which looks commits on the file level, but actually simplifies things - you know instantly whether you're dealing with something with a new or older commit if there's a conflict.

Revisions demarcate the dimension of "time."

* Trunk, branches, tags, and releases are useful concepts, but are all abstracted for svn - all it knows about are copies (lets call them branches). Unlike CVS, there is no difference in svn between a tag and a branch, internally, it's the same. This is why there's some confusion about your setup, since all branching patterns that are up to the repository manager/dev team to abide to.

All branches are just a different path. Your path demarcates the dimension of "location."

* As mentioned, all merges happen locally.

---

Now, lets go through how this works in your numbered scenario.

You have two "branches," one is named */path/trunk*, one is named */path/production*. You also have your local, or *working copy*.

Step 1) is calling 'svn switch' which is a superset of 'svn update' - it will make sure that you're *working copy* is synced with the latest version of */path/trunk* (barring any changes you have made and if there are no intervening changes, otherwise you will need to merge here).

Step 2) you now check in your changes ('svn commit') into */path/trunk*. You are at the HEAD because you have just created the most recent revision. (In svn, no matter what "branch" you are in, you will always be at the HEAD if you update or checkin, since you'll be at the youngest revision, which is all that HEAD means)

Step 3) you call another 'svn switch', and now you hop from */path/trunk* to */path/production*...

Step 4) -- what the switch does now is compare your *working copy* (it should be the same as the HEAD revision of */path/trunk*) to the HEAD revision of */path/production*. You're not really merging anything into either */path/production* or */path/trunk* yet. All your merges are to the *working copy* at this point.

However, you're *working copy* is now set to check into */path/production* on the next commit, so when you next commit...

Step 5) you are now putting what's in your *working copy* (however you decided to merge the issues brought up in Step 4) into */path/production*.


Now you're done, but this is where you need to be careful, because your *working copy* (what you have locally) is set to update against */path/production*. This can lead to problems if you make another change and then do a switch to */path/trunk* (Step 1) because it'll not only compare the differences you made to the working copy, but also any changes anyone else made between */path/trunk* and */path/production*.

So:

Step 6) is to 'svn switch' back to */path/trunk* when you're done with Step 5, so you're local copy is pointing to the trunk again.

Step 0) is that you should 'svn update' right before you start making changes, which if you do Step 6, will make sure you're as synced with */path/trunk* as possible before you're editing to make your life easier.

Hope this helps clarify what's happening.
posted by lhl at 11:34 PM on June 13, 2006


Sorry about the formatting, too used to working in wikis recently. Imagine the stored words are bolded, just for clarity.
posted by lhl at 11:36 PM on June 13, 2006


Wow, thanks everyone. A lot to think about! Maybe I should learn to use it from the command line, I think that would help actually help.

The practice at work (or even more confusingly for the guy who's job I've taken over temporarily) is to have what amounts to a local HD mirror of absolutely everything, so there's a potential breeding ground for problems, because nobody told me to check out or update the files before I did anything!

Getting that straight is a step forward right there. I was assuming that SVN would do everything for me...
posted by AmbroseChapel at 2:30 AM on June 14, 2006


This doesn't directly answer the question, but what IDE are you using for development? I ask because I'm using SVN for developing a financial system right now, and the IDE you use can make abstracting the SVN interface much, much easier. At work we're using IDEA IntelliJ, and it has both SVN and CVS integrated (I haven't tried Eclipse+SVN yet, though I'm sure it's also quite good.)

The nice thing about IntelliJ is that everything is seamless. For instance, clord's comment about always updating before committing is spot-on, but IntelliJ will DIFF the files before committing to make sure you're up-to-date with the latest repository. If you're not, you can't commit... simple as that. When you do a commit, if there are any merge errors the IDE will automatically prompt you to fix them by showing you three windows: your copy (on the left), the SVN copy (on the right) and the IDE's "best-guess" in the middle. Unless you've done significant changes to the file, the best-guess is usually spot-on, though I'd never trust an IDE with automatic merges.

Finally, a good IDE can make browsing the repository so magnificantly easy. I can browse changes made by a particular user, or a particular file, or the entire project if I like. If someone commits changes to a file I'm working on that I think is suspect, I can do a direct side-by-side comparison and the IDE will highlight anything different so I can quickly see what the changes are. Needless to say, rolling-back to previous incarnations (file-level and system-level) is a cakewalk.

When I first started working at the place I'm at, I was using Tortoise for SVN commits and thought it was the bees knees. Then I saw how dramatically easier it all can be with a good development environment.
posted by Civil_Disobedient at 2:37 AM on June 14, 2006


I'm not using an IDE, I'm just using a regular editor. But good point.
posted by AmbroseChapel at 2:16 PM on June 14, 2006


Take a look at "Pragmatic Version Control
Using Subversion
". I read it a few months ago when I first started using SVN -- I used VSS and Perforce before -- and found it to be of great help.

In fact, I've grown to like SVN very much; I am rather impressed with how simple it really is.

Well, good luck!
posted by Mike C. at 3:48 PM on June 15, 2006


« Older I'm losing hair over one of my...   |  Can anyone recognize this them... Newer »
This thread is closed to new comments.