We are currently using a somewhat complicated deployment setup that involves a remote SVN server, 3 SVN branches for DEV, STAGE, and PROD, promoting code between them through patches, etc. I wonder what do you use for deployment in a small dev team situation?
A simple trunk branch contains the most current code, then cut a branch whenever we go live. This seems to work pretty effectively. You can easily go to the previous branch whenever the current branch that you cut for the live system fails. Also, it is easy to fix bugs on the branch that is currently live, and since the branch effectively dies when you cut a new one, there is only ever 1 real branch you need to work on (and then merge fixes from there to the live branch).
When i worked in a small dev team (small meaning me, another programmer and the boss), it was quite the chaotic mess. However we found that Assigning a "gatekeeper" type of process worked for us.
The gatekeeper was the person who had done the most work on the app (in this case, i had 2 projects i developed from the ground up, he had like 4).
Basically, whenever he had to work on my projects, he'd notify me that he was doing work, i'd make sure the repository was up-to-date and buildable, then he would pull down, make his changes, then commit. He would inform me that it was done, i would pull down, build and deploy. If there were DB changes we had a DB Change folder with all the scripts that would correct the DB.
It's obviously got a lot of holes in it, but the process worked for us, and kept us from building over each other.
Three branches just sounds like extra work.
Environmental differences can be handled by having different versions of the relevant files in the trunk. i.e. database.yml & database.yml.prod. The deployment process should be environmentally aware and simply copy the per-environment files over the default ones.
Capistrano is one of the best deployment tools around.
We don't use branches for staging web-related stuff; only for testing experimental things that will take a long time (read: more than a day) to merge back into trunk. The trunk, in 'continuous integration' style, represents a (hopefully) working, current state.
Thus, most changes get committed straight to trunk. A CruiseControl.NET server will automatically update on a machine that also runs IIS and has up-to-date copies of all the extra site's resources available, so the site can be fully, cleanly tested in-house. After testing, the files are uploaded to the public server.
I wouldn't say it's the perfect approach, but it's simple (and thus suitable for our relatively small staff) and relatively safe, and works just fine.
trunk for development, and a branch (production) for the production stuff.
On my local machine, I have a VirtualHost that points to the trunk branch, to test my changes.
Any commit to trunk triggers a commit hook that does an svn export and sync to the online server's dev URL - so if the site is stackoverflow.com then this hook automatically updates dev.stackoverflow.com
Then I use svnmerge to merge selected patches from trunk to production in my local checkouts. I have a VirtualHost again on my local machine pointing to the production branch.
When I commit the merged changes to the production branch, again an SVN export hook updates the production (live) export and the site is live!
We use release branching - this seems to be more efficient for us than the feature branching we were doing.
Don't make different branches for the different environments.
Trunk contains the current "primary" development codebase.
A developer will often create an individual branch for any medium to long-term project that could hose the trunk codebase and get in the way of the other devs. When he's complete he'll merge back into trunk.
We create a tagged-release every time we push code to production. The folder in /tags is simply the version number.
To deploy to production we're doing an SVN Export to Staging. When that's satisfactory we use a simple rsync to roll out to the production clusters.
I personally work locally (development), adding/fixing features and when I think it's ready I commit to trunk (production). On production server I just do an svn update.
I work with a similar situation to that which you currently have. I was tasked with finding a ‘better’ solution and it ran something along the lines of the following.
The live branch represents the servers in their current state.
Any development work should be done in a branch that is taken from live. This could be a one person half hour job or a year long multi team project. As often as is liked changes to live can be merged into these development branches.
Before a piece of work goes live, changes from live are merged again and it is tagged as a potential release. This release is tested on the staging environment and if it passes testing the new live is taken from the tag.
It is possible to merge several pieces of work into one release if that works better.
This means that it is fairly simple to keep development branches up to date with live and if a piece of work in development is dropped there is minimal tidying up to do.
To change from working on one project to another a developer can simply svn switch their local working environment to a different branch.
One of the problems we have had with the system as you describe is that DEV can get out of date with PROD fairly quickly, so you are not developing against the live and it is not easy to spot cross dependencies until stage. The above solution solves these issues while still remaining fairly lightweight.
I haven't had any trouble with the common tags/branches/trunk organization.
General ongoing development happens in trunk.
Maintenance of a release in production happens in the appropriate release branch.
Changes to release branch which are still relevant to trunk are merged.
When a new version is ready for deployment it is tagged from trunk, then a branch is created from that tag. The new release branch is checked out to the server, parallel to the current release. When it's time to switch, the paths are juggled ("mv appdir appdir.old && mv appdir.new appdir").
Developers supporting the production release then svn switch their working copy to the new branch, or do a fresh checkout from it.
I highly recommend the book (currently in rough cuts) Continuous Delivery, which describes a full process for managing software delivery, based on continuous integration principles (among others).
I strongly dislike the branch and merge approach, as it can get very messy, and is pretty wasteful since you end up spending time on activities which don't actually deliver any new value. You've already developed, tested, and fixed your code once, why create a situation (copying the code to another branch) which requires you to redo this work?
Anyway, the way to avoid branching and merging is to build your deployable artefacts from trunk, and promote the built artefacts (rather than source) as it passes test, staging, etc. This way you are 100% sure that the thing you're putting into production is the same thing you've tested.
If you've got different features which may need to be released on different schedules, changing your approach to how you implement (make functionality configurable, or better yet modular) can help you keep a single development trunk.