tags:

views:

105

answers:

4

I have an repository for an app that I'm working on that includes a configuration file. Currently, I distribute with a .dist extension, and have the user rename the file before editing it.

nate:~/myAwesomeApp% git ls-files 
.gitignore
README
config.dist
glorious_support_lib.p
bestProgramEvar.f90

This is fine and dandy, and the actual config is ignored.

nate:~/myAwesomeApp% cat .gitignore 
config

It would be sweet, however, if I could just distribute that config file under its real name and ready-to-edit, while leaving it ignored so that a newly cloned copy of the repository has a "functional" distribution, and it is not overwritten, clobbered, or otherwise molested, and such that users don't have to worry about pushing or publishing their super-secret configuration details to the interwebs via an unintended git commit -a -m 'hurrrr derp! oopsies!' && git push

Is there a way of doing this? Of having git keep around a single original version of the file that gets cloned out, but is thereafter ignored?

I'm sure this has been asked before, but for the life of me, my google-fu has failed. Lay the schoolin' on deep, SO.

+6  A: 

I'd probably include an 'install' script of some sort that copied 'config.dist' to 'config'.

I don't think there's a way to have a file both not-ignored and ignored.

Jonathan Leffler
That's basically what I'm doing now. It would just be sweet if there were an "ignore after commit xxxxxx" ability.
sleepynate
@sleepynate Maybe a post commit hook checking the commit xxxxxx and adding something to .gitignore?
takeshin
+3  A: 

This is a good question, but AFAIK there is no git solution for this.

Few workarounds:

  • configure your app to read config.dist when config is not present (e.g. PHPUnit uses this technique)
  • use build script to do rename for you (e.g. ant or phing)
  • use git hooks to rename the configs
takeshin
I think `post-checkout` runs on clone.. but does the hook come down with the repo on initial clone? How does that look?
sleepynate
@sleepynate This will be hard to do. Just tested - hooks are not cloned with the repo on `git clone [repo]`. I thought about git hooks used during development. I didn't consider cloning as a distribution technique of the app.
takeshin
Oh sorry. I will edit for clarity. This is for the end user when they clone. i already have an `if [ ! -e config ] ; then cp config.dist config ; fi`
sleepynate
+1  A: 

As others have pointed out, there is no magical solution for this in Git. And as far as I know, it's the same with other version control systems.

Hooks are also of no solution here, if they would work this way, that would be a serious security threat - just by cloning a repo, an evil code could execute in your machine.

But to use your app, the user has to do at least one more thing besides cloning it with git: running your app.

  • If modifying the config file is not required for running the application, then if your program does if [ ! -e config ] ; then cp config.dist config ; fi on startup, then that should be IMHO quite enough. Additionally you should have warning inside config.dist which says you shouldn't modify this file, but make a copy of it instead.

  • If the modification of config file is required, then starting the program without config file could start up some installation mode, that asks the user to enter the needed configuration options and saves them.

  • A third possibility is that your app is unable to modify the config file when it starts up (maybe it's just some JavaScript + HTML files). In that case I see no other option than to have some separate build script or let the user just manually do it.

Rene Saarsoo
+1  A: 

You can also version and distribute:

  • a .gitattributes files declaring a filter driver (for only 'config.dist')
  • a smudge script which will detect that content and generate the final (and private, as in "non-versioned" config file)

Now that is bending a bit what a filter driver is about (it is about modifying the content of a file, regardless of its "state", i.e its full path and name). But it can work.
The .gitattributes would contain:

config.dist  filter=generateConfig

alt text

And you can register your smudge script (applied during the checkout step when creating/updating the working directory) like:

git config --global filter.generateConfig.smudge /path/to/generateConfig
VonC