git config 中的 Shell 变量扩展

Posted

技术标签:

【中文标题】git config 中的 Shell 变量扩展【英文标题】:Shell variable expansion in git config 【发布时间】:2012-06-30 23:57:39 【问题描述】:

我有一个 shell 变量,它指向我所有配置文件所在的目录。假设变量是用export RC=$HOME/rc 创建的。我在配置目录中有一个全局忽略文件:~/rc/globalgitignore

我的问题是,如何在我的 .gitconfig 文件中扩展 RC 变量?

我已经尝试了以下方法:

excludesfile = $RC/globalgitignore

excludesfile = !$RC/globalgitignore

excludesfile = !echo $RC/globalgitignore

excludesfile = !$(echo $RC/globalgitignore)

这些解决方案都不起作用。

如果我输入完整路径,这是唯一可行的方法:excludesfile = ~/rc/globalgitignore,但是如果将我的 rc 目录移动到其他位置,我必须更改路径。

【问题讨论】:

【参考方案1】:

你不能。 git-config(1)不支持环境变量扩展,只支持有限的类型转换和路径扩展:

类型说明符可以是 --int 或 --bool,以使 git config 确保变量属于给定类型并将值转换为规范形式(int 的简单十进制数,a "布尔值的 true" 或 "false" 字符串),或 --path,它执行一些 路径扩展(参见下面的 --path)。如果未传递类型说明符,则不会对值执行检查或转换

--path 的文档指出:

--路径

git-config 将将 ~ 扩展为 $HOME 的值,并将 ~user 扩展为指定用户的主目录。此选项在设置值时无效(但您可以从命令行使用 git config bla ~/ 让您的 shell 进行扩展)。

“扩展”一词在git-config(1) 中没有出现在任何不同的上下文中。那么,鉴于任何地方都没有记录此类功能,您是如何想到它应该这样做的呢?

为了扩展环境变量,您必须自己预处理 Git 配置文件,即通过创建模板文件,并在将文件复制到 $HOME 目录之前使用脚本扩展变量。

如果是关于点文件管理,那么就按照所有人的做法:将它们放在一个目录中,然后从您的$HOME 向该目录添加符号链接。

【讨论】:

之前我将所有配置文件从rc 目录链接到我的主目录。为了省略这些链接,我创建了RC 变量并且我的大部分程序都使用它。顺便说一句,~ 已扩展,当您使用 git config alias ... 时,您可以使用 shell commandos 和变量扩展。 @SvenK:请阅读git-config(1)git-config(1) 扩展 ~ 的事实并不“自动”意味着变量扩展甚至 shell 命令也受支持。 ~git-config专门处理当且仅当使用--path 类型说明符检索值。这是git-config 支持的唯一 种扩展。我已经更新了我的答案以包含来自git-config(1) 的相关部分 这有点令人沮丧,因为我不能只为我的整个系统指定我的 http[s]?_proxy 环境变量;由于某种原因,我也必须在我的 gitconfig 中指定它。对于不在家或小型开发商店工作和/或根据工作地点而坐在不同网络上的人来说,这很烦人。 @RobertGrant 我很确定 Git 在您的环境中使用 $http_proxy$https_proxy @lunaryorn 我没有观察到这种行为; this 家伙同意。【参考方案2】:

我在配置中使用 bash 脚本来启用变量扩展。只需在 .bashrc 中导出您需要的变量并在脚本中使用它:

在我的 ~/.bashrc 中:

export TESTVARIABLE="hello"

在我的 ~/.gitconfig 中:

[alias]
    test = !bash -c '"echo \"Value: $TESTVARIABLE\";"'

在我的 bash 提示符下:

bash> git test
    Value: hello 

另一种方法是在你的 shell 的 rc 中添加一个 git config 命令。例如,我的 .bashrc 中有:

git config --global user.name "$USER@$HOSTNAME"

我在所有机器上都有相同的配置,通过添加它,我可以区分来自不同机器的提交。你也可以这样做并添加到你的 shell rc:

export RC="$HOME/rc"
git config --global core.excludesfile "$RC/globalgitignore" 

【讨论】:

gospes:我尝试了您为电子邮件字段建议的第一种方法。结果电子邮件(我在提交信息中看到)等于字符串“"。想法? @tivoni @gospes 的示例仅有效,因为它在 git alias 组中【参考方案3】:

使用 Git 2.31(2021 年第一季度),您可以考虑通过环境变量使用配置变量-值对(它调整了 GIT_CONFIG_PARAMETERS 编码变量/值对的方式,使其也更加健壮)。

请参阅commit d8d7715、commit b9d147f、commit 1ff21c0、commit b342ae6、commit ce81b1d(2021 年 1 月 12 日)和 commit b0812b6(2021 年 1 月 7 日)Patrick Steinhardt (pks-t)。 请参阅 Jeff King (peff) 的 commit f9dbb64、commit 13c4495(2021 年 1 月 12 日)。(由 Junio C Hamano -- gitster -- 合并到 commit 294e949,2021 年 1 月 25 日)

config:添加通过--config-env 传递配置的新方法

合着:Jeff King署名:Patrick Steinhardt

虽然已经可以通过 git -c <key>=<value>(man) 传递运行时配置,但当值包含敏感信息时可能不适合使用。 例如 如果想将http.extraHeader 设置为包含一个身份验证令牌,那么通过-c 这样做会轻易地泄露这些凭据,例如ps(1),通常还显示命令参数。

为了在不泄露凭据的情况下启用此用例,此提交引入了一个新开关 --config-env=<key>=<envvar>

它不是直接为给定键传递值,而是允许用户指定环境变量的名称。 然后该变量的值将用作键的值。

git 现在包含在其man page 中:

[--super-prefix=<path>] [--config-env <name>=<envvar>]

git 现在包含在其man page 中:

--config-env=<name>=<envvar>

-c <name>=<value>,给出配置变量 '<name>' 一个值,其中<envvar> 是一个名称 从中检索值的环境变量。

不像 -c 没有直接将值设置为 空字符串,而环境变量本身必须是 设置为空字符串。

如果<envvar> 不存在则错误 在环境中。 <envvar> 不能包含等号 避免与包含一个的 <name>s 产生歧义。

这对于您想要传递临时性的情况很有用 git 的配置选项,但在操作系统的 where 上这样做 其他进程可能能够读取您的命令行 (例如/proc/self/cmdline),但不是您的环境 (例如/proc/self/environ)。 该行为是默认的 Linux,但可能不在您的系统上。

请注意,这可能会增加变量的安全性,例如 http.extraHeader 敏感信息所在的位置 价值,但不是例如url.<base>.insteadOf 在哪里 敏感信息可以是密钥的一部分。

在你的情况下,测试一下:

git --config-env=core.excludesfile=RC config core.excludesfile
# or (Git 2.32+ only)
git --config-env core.excludesfile=RC config core.excludesfile

core.excludesfile 的值应该是 $RC(它应该引用完整的文件路径,而不仅仅是它的父文件夹)


注意:在 Git 2.32(2021 年第二季度)之前,“git --config-env var=val cmd(man)被接受(只有 --config-env=var=val 被接受)。

参见commit c331551、commit 9152904(2021 年 4 月 29 日)Patrick Steinhardt (pks-t)。(由 Junio C Hamano -- gitster -- 合并到 commit 5f586f5,2021 年 5 月 7 日)

git: 支持 --config-env 值的单独 arg

签字人:Patrick Steinhardt审核人:Jeff King

虽然没有这样记录,但许多***选项,如 --git-dir--work-tree 支持两种语法:它们接受选项及其值之间的等号,并且它们支持选项和值作为两个独立的论据。 最近添加的--config-env 选项仅支持带等号的语法。

通过接受这两种语法并添加测试来验证这两种语法来缓解这种不一致。


但还有更多,仍然使用 Git 2.31:

config: 允许通过 envvar 对指定配置条目

签字人:Patrick Steinhardt

虽然我们目前有 GIT_CONFIG_PARAMETERS 环境变量,可用于将运行时配置数据传递给 git 进程,但它是内部实现细节,不应由最终用户使用。

除了仅供内部使用之外,这种传递配置条目的方式还有一个主要缺点:需要解析配置键,因为它们在单个变量中包含键和值。 因此,留给用户对值中任何可能有害的字符进行转义,如果值由第三方控制,则很难做到这一点。

因此,此提交添加了一种通过环境添加配置条目的新方法,从而消除了此缺点。 如果用户传递了GIT_CONFIG_COUNT=$n 环境变量,Git 将为[0,n) 中的每个i 解析环境变量对GIT_CONFIG_KEY_$iGIT_CONFIG_VALUE_$i

虽然git -c <name>=<value>(man) 可以实现相同的效果,但对于潜在的敏感信息可能不希望这样做。 例如 如果想将http.extraHeader 设置为包含身份验证令牌,则通过-c 这样做会轻易地通过例如泄漏这些凭据。 ps(1),通常还显示命令参数。

git config 现在包含在其man page 中:

GIT_CONFIG_COUNT

GIT_CONFIG_KEY_<n>

GIT_CONFIG_VALUE_<n>

如果GIT_CONFIG_COUNT 设置为正数,则所有环境对 GIT_CONFIG_KEY_<n>GIT_CONFIG_VALUE_<n> 最多为该数字 添加到进程的运行时配置中。

配置对是零索引的。 任何缺少的键或值都被视为错误。 空的GIT_CONFIG_COUNT 被视为与GIT_CONFIG_COUNT=0 相同,即没有 处理对。 这些环境变量将覆盖值 在配置文件中,但将被任何显式选项覆盖 通过git -c.

这对于您想要生成多个 git 命令的情况很有用 具有通用配置但不能依赖于配置文件, 例如在编写脚本时。

例如:

    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.*" 

将打印:

pair.one foo
pair.two bar

【讨论】:

以上是关于git config 中的 Shell 变量扩展的主要内容,如果未能解决你的问题,请参考以下文章

shell脚本中大括号的扩展在变量中的问题

Shell 读取用户输入

Git配置文件与git config命令

如何在文本文件中扩展 shell 变量?

Windows 上 Git 路径的位置

windows安装了git以后就可以运行shell脚本了吗