Shell variable expansion in git config
I have a shell variable which points to the directory where all my configuration files are located. Let's assume the variable is created with export RC=$HOME/rc
. I have a global ignore file in the configuration directory: ~/rc/globalgitignore
.
My Question is, how can I expand the RC
variable in my .gitconfig
file?
I already tried the following:
excludesfile = $RC/globalgitignore
excludesfile = !$RC/globalgitignore
excludesfile = !echo $RC/globalgitignore
excludesfile = !$(echo $RC/globalgitignore)
None of these solutions work.
The only way this works if I enter the full path: excludesfile = ~/rc/globalgitignore
, but then I have to change the path if move my rc
directory to a different location.
Solution 1:
You can't. git-config(1) does not support environment variable expansion, but only limited type conversion and path expansion:
The type specifier can be either --int or --bool, to make git config ensure that the variable(s) are of the given type and convert the value to the canonical form (simple decimal number for int, a "true" or "false" string for bool), or --path, which does some path expansion (see --path below). If no type specifier is passed, no checks or transformations are performed on the value.
The documentation for --path
states:
--path
git-config will expand leading ~ to the value of $HOME, and ~user to the home directory for the specified user. This option has no effect when setting the value (but you can use git config bla ~/ from the command line to let your shell do the expansion).
The term "expansion" does not appear in any different context in git-config(1)
. So how did you even get the idea that it should, given that no such feature is documented anywhere?
In order to expand environment variables you have to pre-process the Git config file yourself, i.e. by creating a template file, and expand variables with a script before copying the file to your $HOME
directory.
If it's about dotfile management, then do, what all people do: Put them in a directory, and add symlinks to this directory from your $HOME
.
Solution 2:
I use bash scripts in my config to enable variable expansion. Just export the variable you need in your .bashrc and use it in the scripts:
In my ~/.bashrc:
export TESTVARIABLE="hello"
In my ~/.gitconfig:
[alias]
test = !bash -c '"echo \"Value: $TESTVARIABLE\";"'
At my bash prompt:
bash> git test
Value: hello
The other way of doing it, is to add a git config command in your shell's rc. I for instance have in my .bashrc:
git config --global user.name "$USER@$HOSTNAME"
I have the same configuration on all my machines, and by adding this I can distinguish between commits from different machines. You could do the same and add to your shell rc:
export RC="$HOME/rc"
git config --global core.excludesfile "$RC/globalgitignore"
Solution 3:
With Git 2.31 (Q1 2021), you might consider using configuration variable-value pairs via environment variables (and it tweaks the way GIT_CONFIG_PARAMETERS
encodes variable/value pairs to make it more robust too).
See commit d8d7715, commit b9d147f, commit 1ff21c0, commit b342ae6, commit ce81b1d (12 Jan 2021), and commit b0812b6 (07 Jan 2021) by Patrick Steinhardt (pks-t
).
See commit f9dbb64, commit 13c4495 (12 Jan 2021) by Jeff King (peff
).
(Merged by Junio C Hamano -- gitster
-- in commit 294e949, 25 Jan 2021)
config
: add new way to pass config via--config-env
Co-authored-by: Jeff King
Signed-off-by: Patrick Steinhardt
While it's already possible to pass runtime configuration via
git -c <key>=<value>
(man), it may be undesirable to use when the value contains sensitive information.
E.g.
if one wants to sethttp.extraHeader
to contain an authentication token, doing so via-c
would trivially leak those credentials via e.g.ps(1)
, which typically also shows command arguments.To enable this usecase without leaking credentials, this commit introduces a new switch
--config-env=<key>=<envvar>
.Instead of directly passing a value for the given key, it instead allows the user to specify the name of an environment variable.
The value of that variable will then be used as value of the key.
git
now includes in its man page:
[--super-prefix=<path>] [--config-env <name>=<envvar>]
git
now includes in its man page:
--config-env=<name>=<envvar>
Like
-c <name>=<value>
, give configuration variable '<name>
' a value, where<envvar>
is the name of an environment variable from which to retrieve the value.Unlike
-c
there is no shortcut for directly setting the value to an empty string, instead the environment variable itself must be set to the empty string.It is an error if the
<envvar>
does not exist in the environment.<envvar>
may not contain an equals sign to avoid ambiguity with<name>
s which contain one.This is useful for cases where you want to pass transitory configuration options to git, but are doing so on OS's where other processes might be able to read your cmdline (e.g.
/proc/self/cmdline
), but not your environ (e.g./proc/self/environ
).
That behavior is the default on Linux, but may not be on your system.Note that this might add security for variables such as
http.extraHeader
where the sensitive information is part of the value, but not e.g.url.<base>.insteadOf
where the sensitive information can be part of the key.
In your case, test it out with:
git --config-env=core.excludesfile=RC config core.excludesfile
# or (Git 2.32+ only)
git --config-env core.excludesfile=RC config core.excludesfile
The value for core.excludesfile
should be $RC
(which should reference the full file path, not just its parent folder though)
Note: Before Git 2.32 (Q2 2021), "git --config-env var=val cmd
"(man) were not accepted (only --config-env=var=val
was).
See commit c331551, commit 9152904 (29 Apr 2021) by Patrick Steinhardt (pks-t
).
(Merged by Junio C Hamano -- gitster
-- in commit 5f586f5, 07 May 2021)
git
: support separate arg for--config-env
's valueSigned-off-by: Patrick Steinhardt
Reviewed-by: Jeff King
While not documented as such, many of the top-level options like
--git-dir
and--work-tree
support two syntaxes: they accept both an equals sign between option and its value, and they do support option and value as two separate arguments.
The recently added--config-env
option only supports the syntax with an equals sign.Mitigate this inconsistency by accepting both syntaxes and add tests to verify both work.
But there is more, still with Git 2.31:
config
: allow specifying config entries via envvar pairsSigned-off-by: Patrick Steinhardt
While we currently have the
GIT_CONFIG_PARAMETERS
environment variable which can be used to pass runtime configuration data to git processes, it's an internal implementation detail and not supposed to be used by end users.Next to being for internal use only, this way of passing config entries has a major downside: the config keys need to be parsed as they contain both key and value in a single variable.
As such, it is left to the user to escape any potentially harmful characters in the value, which is quite hard to do if values are controlled by a third party.This commit thus adds a new way of adding config entries via the environment which gets rid of this shortcoming.
If the user passes theGIT_CONFIG_COUNT=$n
environment variable, Git will parse environment variable pairsGIT_CONFIG_KEY_$i
andGIT_CONFIG_VALUE_$i
for eachi
in[0,n)
.While the same can be achieved with
git -c <name>=<value>
(man), one may wish to not do so for potentially sensitive information.
E.g.
if one wants to sethttp.extraHeader
to contain an authentication token, doing so via-c
would trivially leak those credentials via e.g.ps(1)
, which typically also shows command arguments.
git config
now includes in its man page:
GIT_CONFIG_COUNT
GIT_CONFIG_KEY_<n>
GIT_CONFIG_VALUE_<n>
If
GIT_CONFIG_COUNT
is set to a positive number, all environment pairsGIT_CONFIG_KEY_<n>
andGIT_CONFIG_VALUE_<n>
up to that number will be added to the process's runtime configuration.The config pairs are zero-indexed.
Any missing key or value is treated as an error. An emptyGIT_CONFIG_COUNT
is treated the same asGIT_CONFIG_COUNT=0
, namely no pairs are processed.
These environment variables will override values in configuration files, but will be overridden by any explicit options passed viagit -c
.This is useful for cases where you want to spawn multiple git commands with a common configuration but cannot depend on a configuration file, for example when writing scripts.
For example:
GIT_CONFIG_COUNT=2 \
GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="foo" \
GIT_CONFIG_KEY_1="pair.two" GIT_CONFIG_VALUE_1="bar" \
git config --get-regexp "pair.*"
will print:
pair.one foo
pair.two bar