Well I can offer some of the solution: source code control. I use Subversion, but team foundation has source control, and there are a gazillion others out there. For this I'd say you need a few features for sure though. You need to be able to tag versions, you need branches and merging is very nice.
Currently, I'm in your very situation. I have a version in production, a version that has some fixes to that version being tested, the next version that is in pieces now, a version that is based on the main app, but with a bunch of functionality removed and a different way of connecting to the database and a version that is a risky overhaul to some critical functionality that I don't want to impede the progress of the app if it doesn't work/takes a while to finish. Here's how I do it.
The "trunk" of my source tree contains the next version (always) and is the main development line. This contains all of the code related to the project: .net source, sql scripts (or could be DDT packages), documentation, help, setup projects/scripts (the tools to make setup programs)...every thing that is needed to develop and deploy the application. Typically I don't check in the actual setup programs or any of the actual exe or dll files...anything that gets created from source is not in source control.
When I'm getting close to releasing, I create a release branch by copying the entire source tree from trunk. This then becomes a release candidate, which then become the production branch, which is were I'd fix my production code. When I release to production (any time I release to production) I'll also tag that branch (in subversion that is just copying the tree to a new folder), so I can always get to the exact code that is in production. Subversion uses a folder approach, so my structure looks something like:
/branches
/REL-3.0.4
/NetCode
/SqlScripts
/SetupScripts
/Docs
/tags
/REL-3.0.4.9
/NetCode
/SqlScripts
/SetupScripts
/Docs
/trunk
/NetCode
/SqlScripts
/SetupScripts
/Docs
So, current development happens in trunk. I do fixes to production code in /branches/REL-3.0.4. When I release, I'll tag it under /tags and it would become /tags/REL-3.0.4.10.
Then I do risky stuff under branches also. Currently, I'm reworking my search functionality, so my tree also has a branch for that:
/branches
/TRY-gpm-Searches
/NetCode
/SqlScripts
/SetupScripts
/Docs
/REL-3.0.4
/NetCode
/SqlScripts
/SetupScripts
/Docs
/tags
/REL-3.0.4.9
/NetCode
/SqlScripts
/SetupScripts
/Docs
/trunk
/NetCode
/SqlScripts
/SetupScripts
/Docs
How this works is that I check out the code to my local hd, in order to do development. Once I've released a new version into production, I just delete that code off my HD (it's in source control), create the branch for the new production version and check out
that version, so my hard drive stays clean. Also, the source tree gets backed up on the server
religiously.
Now, there are other things to consider, which I sort have figured out.
- SQL updates. You have to have some way to reliably update the db from almost any version to any other version. The DDT was designed for this. I don't use it much though, just for my security db. I check in the packages it creates. I prefer to use SQL scripts and use a tool called DbGhost. In this case, my SQL scripts are my source, so that is what is checked in (creation scripts...no update scripts at all).
- Assembly versions. This is still a bit of a mystery to me. However, I know it's important
- SF version. This one can be nasty. If you upgrade SF from one version to the next, on your development machine, the SF assemblies are in the GAC. Which means that if you want to use the newest version of SF for trunk or an experiment, but not in the production fix (uses an older version), it can get tricky. I'm not sure how to handle this at all. It may mean that the SF dlls need to be checked in also, which would allow proper deployment, but not solve the development issue. Fortunately, this hasn't been a problem as I'm almost always willing to just move all versions to the latest SF version and when I'm not, it usually isn't too long before I can get back on track.
That was a long post! I hope it was a helpful start!