I've always just created cap tasks for each deploy target and used them on the command line:
# deploy.rb
task :stage do
server 10.0.0.1 ...
end
> cap stage deploy
You can also define customize tasks inside each target task, such as a deploy that does cleanup in staging, but doesn't in production.
Since these deploy target tasks are rarely very big, I never really saw the point of something like installing the cap extensions for multi-stage, but I suppose other's situations may be different.
I do think production should be separate from your other environments, otherwise there's a danger that misbehaving processes in staging or the like could affect production performance.
Sometimes I define cap tasks for convenience in staging, such as blasting out the database and reloading it from the most recent production dump. These tasks should check their deploy target via a set variable or the like and refuse to run for production as insurance against a late night typo.
It's tempting to put lots of custom behavior in your deploy.rb, but I've found this tends to bite back and require a lot of maintenance effort as your environment or the cap api's change.
Another practice I've seen with larger environments is to have a shell account with a checkout that tracks the stable branch specifically set up to act as the capistrano control point. You ssh in and run cap commands there instead of locally. This can help avoid issues where your local checkout's deploy.rb has modifications that you aren't ready to use with deploying to production. This is less of an issue with git vs svn, but still one must be careful to think about what their local deploy.rb is at the moment they're running cap commands.
Heroku is really making this stuff easy these days, and EY and others aren't exactly far behind.