Branch-Specific Configuration File Maintenance with Git

Using gitconfig per branch

You can use post-checkout hook for this. Run

$ touch .git/hooks/post-checkout 
$ chmod a+x .git/hooks/post-checkout

Add contents to post-checkout script (edit names and branches as neccessary)

#!/bin/bash
# $3 "0" - checking out file. "1" - checking out branch.
[[ "$3" == "0" ]] && exit 0
branch=$(git status --short -b | cut -d' ' -f2-)
case $branch in
gerrit*)
git config user.name "Personal Name"
echo "changed user.name to Personal Name"
;;
master*)
git config user.name "Company Name"
echo "changed user.name to Company Name"
;;
*)
echo "Some other branch, what should user.name be?"
;;
esac

git - local repository - how to manage different customer config files with same names

Under the following assumptions I would propose to you this solution:

Assumptions

  • You want to track the code with git
  • You want to track the config files (per customer) with git

Possible solution

I think you could get away with the following setup:

  • Having a master branch that contains only the code and no configuration
  • Having two branches per customer e.g. customerA-prod and customerA-test

If possible commit bugfixes that apply to all customers to the master branch and merge it back into the customer branches.

For customer specific alterations use only the customer branches.

In general try to avoid merging customer branches into master.

If it is really necessary make sure that you do not merge any configuration files onto master (delete them, so that master stays clear of config files).

With this proposed setup I think it should be possible to share the code (where needed), track the history of the config files (per customer/environment).

Unclear specification

but whenever I check out the master branch, the config files, since they aren't part of the config branch, they get deleted

I don't understand the problem here.

Maybe you need some customers config files on master in order to develop?
If so you could check out the config files (while still avoiding to commit them by doing something like this)

$ git checkout customerA-prod -- <path-to-config-file>
$ git reset HEAD -- <path-to-config-file>
$ # work, commit (but avoid adding the config file)

The git checkout <branch> -- <file> syntax is useful to get files as they are on other branches onto your current branch.

Does this help?

Keep settings in branch

In your personal branch, you could keep:

  • the GitHub config file unchanged (with no value), but with a different name (config.template for example)
  • a "value file" with your personal value
  • a "smudge" script able to generate the actual config file using the template one and your personal values

That script is triggered on any git checkout as a content filter driver.

Sample Image

That way, you can merge master onto your personal branch as many time as you want, your config values will not be modified.

Using conditional configuration files with Git

No, there isn't, but this is a well-solved problem.

You have a few options:

Version control an example config file

  • Don't store environment-specific data in version control
  • Create a config.example file which lists all the configuration options that need to be specified, and provides sane defaults for development.
  • Users who clone your repo should copy config.example to the real config filename, and add real values
  • Add the real config file's name to .gitignore.
  • Store your production credentials outside of git, but backed up,
  • As a bonus, you can add a setup.sh script, which copies config.example to the real config's location, and populates it with variables for the local environment

As an example, you might have a JavaScript application which needs to know where its database is, and reads this information from config/database.json. You might use something like this:

// config/database.example.json
DATABASE = {
"host": "localhost",
"user": "#TODO",
"pass": "#TODO",
}

To get running in development, you would copy this file to config/database.json, and fill in the values appropriate to your dev environment.

In production, you'd have a config/database.json that contained production values, but was not version controlled.

The repo would have config/database.json in its .gitignore.

Version control environment-specific config files

  • Store X different configuration files, one per environment, call them config.development and config.production etc
  • Symlink the correct one for your environment.
  • add the symlink to .gitignore

If there is anything remotely sensitive in your config file, such as AWS keys or any form of password, you should use the first option - store the configuration option's name, but not its value, and require users to supply their own credentials, obtained through secure channels outside of version control.



Related Topics



Leave a reply



Submit