Using conditional configuration files with Git

I frequently find myself changing a single variable in my project within Git to connect to a different server while on the Development branch (in JavaScript, so I can’t use preprocessor defines).

Is there some way in Git that I can conditionally use one file or another depending on what branch I’m on?

  • git merge strategy for static config file in each branch
  • Efficient way to manage a git repository for local config files
  • Where does git config --global get written to?
  • Why does git difftool use git diff instead?
  • How to set a Git config option when its config file is “$XDG_CONFIG_HOME/git/config”?
  • How to override Git config options by command line parameters?
  • I can’t just commit that change with the different URL specified as doing so would leave it in my commit history, and if I go back to that version later on Master after it has been merged, it will have the development server URL.

  • Can a ref stored outside refs/heads be considered a branch and checked-out and worked-on as a normal branch?
  • Why can't Git merge file changes with a modified parent/master?
  • How to view all pulls from bare repository?
  • Bash script to extract filenames from git whatchanged
  • How to show git log history for a sub directory of a git repo?
  • Read both binary and text from process output
  • 3 Solutions collect form web for “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.

    Note that condition include config is coming, starting with Git 2.13 (Q2 2017).
    The only condition supported as of now is the project name, not the hostname.

    In your case, that would work if each branch is checked out in its own folder (with git worktree: see “Multiple working directories with Git”).

    See commit 86f9515, commit 4aad2f1 (05 Apr 2017) by Nguyễn Thái Ngọc Duy (pclouds).
    (Merged by Junio C Hamano — gitster — in commit a2e2c04, 24 Apr 2017)

    config: add conditional include

    Sometimes a set of repositories want to share configuration settings
    among themselves that are distinct from other such sets of repositories.
    A user may work on two projects, each of which have multiple repositories, and use one user.email for one project while using another for the other.

    Setting $GIT_DIR/.config works, but if the penalty of forgetting to
    update $GIT_DIR/.config is high (especially when you end up cloning
    often), it may not be the best way to go.
    Having the settings in ~/.gitconfig, which would work for just one set of repositories, would not well in such a situation.
    Having separate ${HOME}s may add more problems than it solves.

    Extend the include.path mechanism that lets a config file include another config file, so that the inclusion can be done only when some conditions hold.
    Then ~/.gitconfig can say “include config-project-A
    only when working on project-A” for each project A the user works on.

    In this patch, the only supported grouping is based on $GIT_DIR (in
    absolute path), so you would need to group repositories by directory, or
    something like that to take advantage of it.

    We already have include.path for unconditional includes.
    This patch goes with includeIf.<condition>.path to make it clearer that a condition is required.
    The new config has the same backward compatibility approach as include.path: older git versions that don’t understand includeIf will
    simply ignore them.


    Git 2.14 (Q3 2017) clarifies the documentation.

    See commit ce933eb, commit a076df2, commit 994cd6c, commit 9d71d94 (11 May 2017) by Jeff King (peff).
    (Merged by Junio C Hamano — gitster — in commit ed98060, 29 May 2017)

    The documentation now reads and includes:

    Includes

    The include and includeIf sections allow you to include config
    directives from another source. These sections behave identically to
    each other with the exception that includeIf sections may be ignored
    if their condition does not evaluate to true; see “Conditional includes”
    below.

    The same Git 2.14 reinforce that feature.
    See commit 0624c63 (16 May 2017) by Ævar Arnfjörð Bjarmason (avar).
    (Merged by Junio C Hamano — gitster — in commit b784d0b, 30 May 2017)

    The recently introduced “[includeIf "gitdir:$dir"] path=...” mechanism has further been taught to take symlinks into account.

    The directory “$dir” specified in “gitdir:$dir” may be a symlink to
    a real location, not something that $(getcwd) may return.
    In such a case, a realpath of “$dir” is compared with the real path of the
    current repository to determine if the contents from the named path
    should be included.

    Sounds like you might be interested in a hook; specifically, look into the post-checkout hook. Basically, you would write a small script that modifies a file after checkout based on the value of $(git branch). You don’t mention exactly what would need to happen, but it would likely involve sed.

    You might add the relevant file to a .gitignore file, or maybe write a pre-commit hook, so that your change doesn’t accidentally propagate to the public repo.

    Git Baby is a git and github fan, let's start git clone.