views:

38

answers:

2

We use git for most of the web applications we build in our shop, and though the applications themselves use a variety of technologies (PHP, Rails, etc), we generally have a staging and production server for each site. Typically, these servers have different sets of database credentials as well as different environment-based configuration settings (e.g. caching). Our workflow generally involves maintaining two git branches per project: master, which reflects the production server, and staging, which reflects staging. New features are developed on staging (or a sub-branch) and are merged back to master upon completion and deployment.

My question is with respect to the best way to maintain the configuration files that are branch- and environment-specific. I've seen the answers from similar questions here and here, and neither really satisfies. The main two approaches seem to be a) using .gitignore exclusion to leave config files outside of git's purview, or b) writing reflective, environment-aware code that determines e.g. what database credentials to use based on hostname. My problem with a) is that it only allows one set of config files to exist in the codebase (irrespective of the current branch), so the other environment's config files get lost. b), on the other hand, just seems to require unnecessary modification of the codebase in a way that doesn't feel related to the application's functionality.

Ideally, I'd like a way to "lock" configuration files within a certain branch, so that whenever I checkout master, I get the master config files, and whenever I checkout staging, I get the staging config files. Additionally, merging staging into master shouldn't affect the master config files in any way. To date, we've dealt with this by having folders containing environment-specific configuration files outside of the git root and manually moving the appropriate files into codebase when deploying, but this is of course needlessly hackish (and potentially dangerous).

Is there any way to accomplish this using git?

Thanks for your consideration!

A: 

I assume that usually, master only holds commits that are already in staging. If you add an extra commit to master which contains the differences in configuration between the two branches, then rebasing this commit on top of whatever is pulled from staging should maintain the configuration. This isn't quite as simple as "merging staging into master shouldn't affect master config files in any way", but as you'd get a merge conflict in these cases, it may be close enough.

Andrew Aylett
+2  A: 

Not sure why people think they can get away without some sort of install tool. Git is about tracking source, not about deploying. You should still have a "make install"-type tool to go from your git repo to the actual deploy, and this tool might do various things like template expansion, or selection of alternate files.

For example, you might have "config.staging" and "config.production" checked in to git, and when you deploy to staging, the install tool selects "config.staging" to copy to "config". Or you might have a single "config.template" file, which will be templated to make "config" in the deploy.

Randal Schwartz
Yep, that's generally how I do things. I use a deployment tool (I mostly work with Django so I use Fabric, or Capistrano in the rare instance that I'm working on a Rails app) that automagically moves or sets up symlinks to the proper config file upon deployment.
mipadi