Let's say you have a typical web app and with a file configuration.whatever. Every developer working on the project will have one version for their dev boxes, there will be a dev, prod and stage versions. How do you deal with this in source control? Not check in this file at all, check it with different names or do something fancy altogether?
Currently I have the "template" config file with an added extension for example:
web.config.rename
However, I can see an issue with this method if critical changes have changed.
@Grant is right.
I'm on a team with close to 100 other developers, and our config files are not checked into source control. We have versions of the files in the repository that are pulled with each check out but they don't change.
It's worked out pretty well for us.
What I've done in the past is to have a default config file which is checked in to source control. Then, each developer has their own override config file which is excluded from source control. The app first loads the default, and then if the override file is present, loads that and uses any settings from the override in preference to the default file.
In general, the smaller the override file the better, but it can always contain more settings for a developer with a very non-standard environment.
I version control it, but never push it to the other servers. If the production server requires a change, I make that change directly to the config file.
It may not be pretty, but it works just fine.
The checked-in, plain-vanilla version of app/web.config should be generic enough to work on all developer machines, and be kept up to date with any new setting changes, etc. If you require a specific set of settings for dev/test/production settings, check in separate files with those settings, as GateKiller stated, with some sort of naming convention, though I usually go with "web.prod.config", as not to change the file extension.
We use a template config file that is checked in to version control and then a step in our automated build to replace specific entries in the template file with environment-specific settings. The environment-specific settings are stored in a separate XML file that is also under version control.
We're using MSBuild in our automated build, so we use the XmlUpdate task from MSBuild Community Tasks to update the values.
My team keeps separate versions of the config files for each environment (web.config.dev, web.config.test, web.config.prod). Our deployment scripts copy out the correct version, renaming it to web.config. This way, we have full version control on the config files for each environment, can easily perform a diff, etc.
For a long time, I have done exactly what bcwood has done. I keep copies of web.dev.config, web.test.config, web.prod.config, etc. under source control, and then my build/deploy system renames them automatically as it deploys to various environments. You get a certain amount of redundancy between the files (especially with all of the asp.net stuff in there), but generally it works really well. You also have to make sure that everyone on the team remembers to update all the files when they make a change.
By the way, I like to keep ".config" at the end as the extension so that file associations do not get broken.
As far as local developer versions of the config file, I always try my best to encourage people to use the same local settings as much as possible so that there is no need to have your own version. It doesn't always work for everyone, in which case people usually just replace it locally as needed and go from there. It's not too painful or anything.
We just keep the production config file checked in. It's the developer's responsibility to change the file when they pull it out of source safe for staging or development. This has burnt us in the past so I wouldn't suggest it.
+1 on the template approach.
But since this question has tag Git, the distributed alternative springs to mind, in which customizations are kept on a private testing branch:
A---B---C---D--- <- mainline (public)
\ \
B'------D'--- <- testing (private)
In this scheme, the mainline contains a generic, "template" config file requiring the minimal amount of adjustments to become functional.
Now, developers/testers can tweak the config file to their heart's content, and only commit these changes locally on one a private testing branch (e.g. B' = B + customizations). Each time mainline advances, they effortlessly merge it into testing, which results in merge commits such as D' (= D + merged version of B's customizations).
This scheme really shines when the "template" config file is updated: the changes from both sides get merged, and are extremely likely to result into conflicts (or test failures) if they are incompatible!
On our project we have configuration stored in files with a prefix then our build system pulls in the appropriate configuration based on the current system's hostname. This works well for us on a relatively small team, allowing us to apply config changes to other people's files if/when we add a new configuration item. Obviously this definitely doesn't scale to open source projects with an unbounded number of developers.
I've used the template before, i.e. web.dev.config, web.prod.config, etc, but now prefer the 'override file' technique. The web.config file contains the majority of the settings, but an external file contains environment-specific values such as db connections. Good explanation on Paul Wilson's blog.
I think this reduces the amount to duplication between the config files which can cause pain when adding new values / attributes.
Configuration is code, and you should version it. We base our configuration files on usernames; in both UNIX/Mac and Windows you can access the user's login name, and as long as these are unique to the project, you are fine. You can even override this in the environment, but you should version control everything.
This also allows you to examine others' configurations, which can help diagnose build and platform issues.
The solution we use is to have only the single configuration file (web.config/app.config), but we add a special section to the file that contains settings for all environments.
There is a LOCAL, DEV, QA, PRODUCTION sections each containing the configuration keys relevant to that environment in our config file(s).
What make this all work is an assembly named xxx.Environment which is referenced in all of our applications (winforms and webforms) which tells the application which environment it is operating on.
The xxx.Environment assembly reads a single line of information from the machine.config of the given machine which tells it that it is on DEV, QA, etc. This entry is present on all of our workstations and servers.
Hope this helps.
We have two problems here.
Firstly we have to control the configuration file that is shipped with the software.
It is all two easy for a developer to check in an unwanted to change to the master config file, if they are using the same file in the devolvement environment.
On the other side, if you have a separate configuration file that is included by the installer, it is very easy to forget to add a new setting to it, or to let the comments in it get out of sync with the comments in the devolvement configuring file.
Then we have the problem that developers have to keep there copy of the configuration file up-to-date as other developers add new configuration settings. However some settings like database connection strings are different for each developer.
There is a 3rd problem the question/answers do not cover. How do you merge in the changes a customer have make to your configuration file when you install a new version of your software?
I have yet to see a good solutions that works well in all cases, however I have seen some partial solutions (that can be combined in different combinations as needed) that reduces the problem a lot.
Firstly reduce the number of configuration items you have in your main configuration file.
If you don’t have a need to let your customers change your mappings, use Fluent NHibernate (or otherwise) to move the configuration into code.
Likewise for depency injection setup.
Split up the configuration file when possible, e.g. use a separate file to configure what Log4Net logs.
Don’t repeat items between lots of configuration files, e.g. if you have 4 web applications that are all installed on the same machine, have a overall configuration file that the web.config file in each application points to.
(Use a relative path by default, so it is rare to have to change the web.config file)
Process the development configuration file to get the shipping configuration file.
The could be done by have default values in the Xml comments that are then set in the configuration file when a build is done. Or having sections that are deleted as part of the process of creating the installer.
Instead of just having one database connection strings, have one per developers.
E.g first look for “database_ianr” (where ianr is my username or machine name) in the configuration file at run time, if it is not found, then look for “database”
Have a 2nd level "e.g. -oracle or -sqlserver" make it quicker for developers to get to both database systems.
This can of course also be done for any other configuration value.
Then all values that end in “_userName” can be striped out before shipping the configuration file.
However in the end what is you is a “owner of configuration file” that takes the responsibly of managing the configuration file(s) as above or otherwise. He/She should also do a diff on the customer facings configuration file before each shipment.
You can’t remove the need for a caring person some this short of problem.