Search code examples
gittestingconfig

How Do I Use `GIT_CONFIG` Environment Variable


I've read the git-config docs and checked SO questsions here and here, but I cannot seem to find an answer.

I am writing a custom tool for Git and I would like to test it. I would like to backup my global and system Git config files and then write to new config files in my tests so I don't override what I already have in place (FYI, I am testing against multiple different portable (locally built) versions of Git both for Linux and Windows in a subdirectory of my project).

My initial thought would have simply been to use cp:

# Backup the system config file
# NOTE: How do I test this automatically? (I have to enter root password)...
sudo cp ${PREFIX}/etc/gitconfig ${PREFIX}/etc/gitconfig.bak

# Backup the global config file
cp ~/.gitconfig ~/.gitconfig.bak

# DO MY TESTS HERE

# Restore system config file and delete backup
sudo cp ${PREFIX}/etc/gitconfig.bak ${PREFIX}/etc/gitconfig
sudo rm ${PREFIX}/etc/gitconfig.bak

# Restore global config file and delete backup
cp ~/.gitconfig.bak ~/.gitconfig
rm ~/.gitconfig.bak

However, I don't see this being done in t/t1300-config.sh (as of the time of this writing, the current version of the master repo is v2.32). The closest thing being done that I see is this (lines 2147-2158):

test_expect_success 'write to overridden global and system config' '
    cat >expect <<EOF &&
[config]
    key = value
EOF
    GIT_CONFIG_GLOBAL=write-to-global git config --global config.key value &&
    test_cmp expect write-to-global &&
    GIT_CONFIG_SYSTEM=write-to-system git config --system config.key value &&
    test_cmp expect write-to-system
'

I don't understand what is going on here. The Git Docs explain GIT_CONFIG is an environment variable that can be set to override the git config file, but if I enter the above commands in my terminal, no file write-to-global or write-to-system is created (and these are not functions in the test script either).

Can someone explain how to properly use the GIT_CONFIG environment variable and what's the right way to do this in a test script?


Solution

  • The environment GIT_CONFIG variable is ancient, predating Git 1.5.3, where git config --file was added. It still exists as a way to trick other Git commands into acting as if they were given a --file argument to pass to git config. It probably should be removed, but, well, Git maintains a lot of backward compatibility! It reminds me of the old joke about Intel putting the "backwards" in "backwards compatible"...

    Until Git 1.8.2, git clone relied on setting GIT_CONFIG internally, then unsetting it. It looks (from the linked questions and their answers) like there may still be some leftovers here.

    (I found the above two items in the release notes. All added snark is my own though.)

    Git version 2.31.0 added new GIT_CONFIG_COUNT and GIT_CONFIG_KEY_$i, GIT_CONFIG_VALUE_$i environment variables. They seem to be intended to add some degree of security, to avoid passing -c arguments that can be read from ps reading the command line. But since ps can (at least on many systems) also read environment variables, I think this "security" is mostly illusory.

    Can someone explain how to properly use the GIT_CONFIG environment variable and what's the right way to do this in a test script?

    Unless you need to put configurations somewhere other than .git/config, the short answer is "don't use this at all". If you want to make sure that the system configuration file does not affect you, set GIT_CONFIG_NOSYSTEM (to any value although I'd use true just for consistency). You can then set $HOME and $XCD_CONFIG_HOME to make other Git commands look for the global Git configuration file in a predictable location, and of course the local and per-work-tree configuration files' locations are predictable already.

    This method is a bit clumsy.

    ... in t/t1300-config.sh

    This very recently (not in any release version, but in both 2.32.0 release candidates) gained the new GIT_CONFIG_SYSTEM and GIT_CONFIG_GLOBAL variables. They're intended to fix some of the clumsiness of the above. Unless you're building the various release candidates or other cutting-edge branches, you won't have this at all. But this does seem to me a better way to deal with all of this.