On most of these projects, the preferred method used by developers is to keep multiple config files in the source repository. These are distinguished by simple renaming of the files (such as app.config, app_qa.config, app_prod.config.) In theory this should work - once you have the config files set up for each environment, deployment requires replacing the file as appropriate. And if you use a .bat file or build script, the file rename will be automatic.
The scenario usually overlooked, however, is the case where something in the config changes. Maybe a new web service is being used by the application. Or perhaps a new assembly needs to be referenced. In my experience, the developer often makes the changes to the main file (app.config), but forgets to make the same changes to the others. During development the code appears to work fine. Unfortunately, the app fails to run in the QA environment. Usually, some amount of time is spent by the developer before realizing that the problem is with the config.
To reduce this sort of issue, I recommend only keeping one config in the source repository. This config will contain the values necessary to run in the development environment. During the build process, the config is updated for the target environment. The MSBuild Community Tasks contains a FileUpdate task that makes this easy.
Let's say you have a config file with the following:
<add key="MyWebService" value="http://localhost/service/MyWebService.asmx" />
The msbuild script to deploy to QA would contain: