Semi-editable Files (eg config files) and version control – best practices?
So, I killed the build today by checking in a config file. It knows where the server is (think SQL server or the like), and I’ve been working against the server which runs on my box. Normally, or rather, under other circumstances, we’d run against the central server. The daily build, of course, didn’t find ‘my’ server, hence the breakage. Then again, editing the config file to point to the ‘normal’ server before the checkin, and editing it again after checkin is tendious.
I’ve been tempted to have VC just ignore the config file, so that it doesn’t get checked in accidentally. On the other hand, the repository should contain a clean, usable version of the file. I can’t possibly ignore it and have it checked in at the same time, now, could I?
So, what I’m looking for would be a way to have a file which, errr, which checks out, but never checks in. At least in the most common case – should the config file change significantly, some special procedure to get the new version into the repository would be doable.
If You folks have come across this problem before, I’d be interested about any solutions You have found. As long as they don’t break the build, that is 😉
8 Solutions collect form web for “Semi-editable Files (eg config files) and version control – best practices?”
What you can do is have a default config file that stays unchanged, unless some new config is added. Then you have a different file that overrides the default file’s configs.
Only config.Default.xml is source controlled. config.User.xml contains only the configurations that are different for you. So, say you are testing on a local SQL server, you put only the connection string in there and it will override the config.Default connection string.
Take a look at .Net Framwork Application Configuration, it does most (if not all) of the work for you.
One method I’ve used is to have two versions of the config file, and have the installer script pull the correct version.
Both files contain the same keys, but one contains ‘dev’ values and the other contains the values we expect to deploy and be edited in the field.
We store these sort of files in our source control system, and have different folders for the environment we’re building for.
So we have:
Dev Test Live
There are subfolders under these for other environment specific files.
- *.(config | xml)
- *.(config | xml).cert
- *.(config | xml).production
Hudson deletes the initial file and deploys the correct file for the correct environment (currently only cert).
This allows developers to document and develop production, cert and development level config files independently and have them versioned separately in SVN.
I think the accepted answer is good, but depending on your requirements, it may have limitations.
We use the following approach. Note that we are .NET shop using VS and make use of MSBuild (inbuilt, community and custom) tasks.
- App.config is ignored by version control but included in the project.
- App.default.config is under version control and also included in the project. Instead of hard-coding things that can change, e.g. db connection strings, we use tokens instead.
A project’s BeforeBuild task looks for existance of App.config and if not found copies App.default.config to App.config. Also, the build server always deletes App.config if it exists on a CI build (ensures clean config). We also then use the MSBuild Community FileUpdate task to replace the tokens with the appropriate values based on whatever is building the project.
For example, a fresh developer checkout can setup db connection strings for a local database, a nightly build can setup for the nightly db, etc.
Were I work we have separate config files for deploys. So the config files in our solutions are the development versions and people can change them to their heart’s content. These config files are never deployed anywhere.
The config files that are deployed are stored in a separate location in our source control provider. If someone needs to make a config change that will be deployed they have to modify this version instead.
For each configuration file x, create a file that you do check-in called x.dist, which is the default distributed configuration. After the developers check out, have a script that copies each x.dist file to x, where they can customize x as much as necessary. This script can be re-run to update the files following major changes, or developers can manually merge in their changes.
For deployment, you can check in your live deployment files and have your start-up scripts refer to them explicitly (e.g. –config x.production).
This approach is used, for example, in how WordPress is distributed (you must copy a template wp-config.php file) or in development projects that use autoconf (where the configure.ac is checked in but the configure file must be generated by each developer; a special configure file is built for distribution in tarballs at release time).
The accepted answer is good. However, it is possible to do what you wanted to (4 years ago), and maintain just a single config file which checks out and never checks in — if your version control system has the concept of changelists. I have done this in Perforce:
Check out the config file and keep it in its own changelist. When you commit, commit only the other changelists; this is easy to remember if you name your config file changelist something like “DO NOT COMMIT”.
An advantage of this system is that if someone else changes the production version of the config file — i.e. the one which exists on the server, and which everyone is maintaining a modified local version of — then you will be notified of possible conflicts when you get the config file from the server. With a solution like that suggested in the accepted answer, you might keep silently overriding the new production settings with your local settings, which could break your local build or cause you to break the build when you next commit.