Reputation: 31910
It's very common to have at least one configuration file in any project. Every time I share project with git
, I have the same problem with:
Obviously, configs have to be ignored somehow to prevent developer specific data to flood main repository. Now there are several ways I used to use, each with some flaws:
.gitignore
the config files
.git/info/exclude
or set git update-index --assume-unchanged ...
to the file
.gitignore
)_original
while having the real files in .gitignore
. Each developer then renames files to real names
Are there any other, possibly, better ways to handle this? I suspect I'm missing something, some plugin at least.
Upvotes: 83
Views: 23134
Reputation: 23
A very simple enhancement to option 3 is to have your project detect when the configuration file is absent and automatically create it by copying the distributed template. At that point it should either alert the user to the path of the newly-created configuration file, or prompt the user for values to populate it with.
As I see it the main advantages of this approach are that it holds the user's hand enough to be relatively plug-and-play, and it's straightforward enough that it doesn't leave room for accidentally committing your personal config file. It's not a particularly clever solution, but it's easy to implement and does the job.
Upvotes: 0
Reputation: 31910
Another very common option, popularized by The Twelve-Factor App, is to not have any configuration variables hardcoded into files, but rather load them from environmental variables. This way, the files in repository don't need any special treatment.
Upvotes: -1
Reputation: 2434
A lot of good options listed. A few more options to mention:
apply-config /path/to/my_git1
, save-config /path/to/my_git1
which copy in, or save configuration files for the main GIT repo.
Upvotes: 0
Reputation: 16941
Since it took me a while to figure out a working solution with @VonC 's hints, here's a full example of how to ignore passwords with a git clean filter in an Objective-C header file.
Assume you have a default config script named Config.h
containing this
// Change "12345" to your password
#define kPass @"12345"
#define kConstant 42
Create a script hidepass.sh
that matches the critical line(s) and prints the default line instead
#!/bin/sh
awk '{ if (/#define kPass/) print "#define kPass @\"12345\""; else print $0; }'
exit 0
Make the script executable and add it to the repo
Tell git to filter your config file by adding this line to .gitattributes
(also add .gitattributes to your repo)
Config.h filter=hidepass
Tell git to use the hidepass.sh
script for the hidepass filter during clean:
git config filter.hidepass.clean ./hidepass.sh
That's it, you can now change the password in Config.h
but git will not commit this change because it always replaces that line with the default line on checkin.
This is a quick solution for a one-line password, you can go crazy and e.g. end the lines to be ignored with a special string and check for lines with that string.
Upvotes: 6
Reputation: 118742
I saved my local config changes to a git stash. I use git stash apply rather than pop, so that I never remove it from the stash queue. That way I can use reset --hard whenever I feel like it.
Upvotes: 2
Reputation: 9255
Having no experience with Git, but having dealt with the same issues in other contexts (Hibernate login creds in a Spring JUnit suite, or ANT scripts), for anything that is user-specific or depends on a user's local environment:
<sysproperty key="jdbc.username" value="${jdbc.username}"/>
, where jdbc.username
is a system variable (that you can set in Eclipse).Developers can check in whatever they want, because the conf is user-agnostic.
Upvotes: -1
Reputation: 1323463
Filter drivers are the "automatic" way of implementing option 3, as detailed in "when you have secret key in your project, how can pushing to GitHub be possible?":
The smudge
script will, on checkout:
From there the developers can make any kind of modification they want to those config files.
It won't matter, because the clean
script will, on commit, restore the content of that file to its original (template) value. No accidental push there.
Upvotes: 23
Reputation: 2655
For the two cases you mention:
sensitive information (each developer have different DB passwords etc)
Write your scripts to so that these sensitive files are stored in the developer's home directory, rather than in the project directory.
task specific information (when developer works on certain task where one needs to change some settings)
I usually have the default settings checked into the repository, and then when you prepare your commits, you can easily check if you've modified any of those settings, and revert them before you commit.
Upvotes: 2
Reputation: 301077
In projects I have been, we have a default config, and developers have their own config at a particular location outside version control ( convention over configuration ) - the values from latter are used to override those in the former.
We started using encryption for sensitive details in the config: Handling passwords in production config for automated deployment
In case of git, you can look at git attributes filter attribute
to do both the replacement of local values and decryption of sensitive values in an automated way.
You can also have submodules which have say the production.yml
and with restricted access to the submodule repo.
Upvotes: 3
Reputation: 3450
One thing I can think of is similar to method 2 and method 1 above. Where you have a directory where you store complex things that are unique to the site such as directories for config files, user uploaded files, etc.
You keep just the config file itself out of version control, but then you have a dummy copy that is named slightly differently from what the site actually uses and this file contains detailed instructions as to the config parameters and to make a renamed copy.
For example, lets say you have a "site_profile" directory. In this directory you create a file called "README.settings.php" along with a "files" directory that contains user uploaded files (from both admin and front-end users). All of this is under version control.
However, the site will run its settings from "settings.php" which won't exist in here. But if you were to rename the "README.settings.php" to "settings.php" then you would have the config file you need (after you put in your custom settings of course).
This will allow you to tell the other developers what they need out of their config file while keeping your own config file out of the mix. Just set your config file to be ignored or never do a blanket commit for that directory and lower.
Its what we do with Drupal sites where I work and it works really well.
Upvotes: 2
Reputation: 1908
The way we did it on the last project i worked on was to have a master config file that loaded a users local config file if it was present which could overwrite the defaults set in the master if specified and declared its own config info if not present in master. The local file was added to gitignore. That way all common stuff could all be shared and some config always present and each developer can modify their local.
Upvotes: 20