将整个Git配置导出以与GIT_CONFIG一起使用

5

有没有办法将当前正在使用的git配置(本地,全局,系统)全部转储到一个文件中,然后可以将该文件用作GIT_CONFIG文件?

类似于:

$ git config --list > mygit.cfg
$ GIT_CONFIG=mygit.cfg git clone /path/to/repo.git

遗憾的是,上述内容并没有真正做什么(配置没有从mygit.cfg文件中读取,而是从标准位置读取)。

此外,像下面这样做也不行:

$ git config --file mygit.cfg --unset foo.bar

出现以下错误:

fatal: bad config line 1 in file mygit.cfg

据我所知,原因是所有 git 配置文件必须是 INI 格式的文件。然而,git config --list 命令输出的是一个简单的 key=value 列表,而 git 无法将其用作 GIT_CONFIG 文件。

我的用例如下:

  • 我在自动构建主机上遇到了一些与 Git 相关的问题(与克隆第三方代码库有关),这些问题是由 Git 配置设置引起的;
    • 因为它是一个自动构建器,更改不持久化,所以我必须能够在脚本中修改系统;
  • 我真的不关心(也不想烦恼)这个配置存在于哪个级别(本地、全局、系统等),因为配置是由自动构建器创建的;
  • 修复 Git 问题涉及取消设置其中一个配置值;
    • 不幸的是,似乎 git-c 标志只允许设置值,而不能取消设置它们;
  • 我的想法是只需创建一个累积的 Git 配置,从该配置中删除有问题的键,并使用修改后的配置执行我需要的一些操作。之后,我想恢复到原始配置。

一个天真的方法是将各种配置级别的文件简单地连接起来:

cat /etc/gitconfig ~/.gitconfig .git/config > mygit.cfg

不幸的是,这样做行不通,因为我不知道配置文件的位置(耶:多平台构建器!)。(另外:配置文件的实际位置是 Git 的实现细节;我不想依赖于这样的实现细节)

那么,我能以一种可以在 Git 中使用的方式转储我的 Git 配置吗?

3个回答

1
问题在于git config --list输出的格式不适合在GIT_CONFIG中使用。必须解析输出并重新创建新的配置文件。这个脚本可以帮助你开始:
git config --list |
while read line; do
    git config -f cfg \
        "`echo $line | sed 's/=.\+//'`" \
        "`echo $line | sed 's/^.\+=//'`"
done

两个seds将key=some value拆分为两个单独的参数;如果它们包含空格,则用引号括起来。

该脚本创建一个新的(或更新现有的)配置文件cfg

替代实现-仅列出键并单独获取值:

git config --list --name-only |
while read key; do
    git config -f cfg "$key" "`git config $key`"
done

omg. 非常丑陋但有点用!; 看起来你的脚本无法正确处理空值。第一个 sed 表达式(用于提取键)应该改为 's/=.*//' - umläute
请查看更新 - 可替代实现。这仍然不是完整的解决方案 - 它无法处理多个值。 - phd

1

可以使用类似以下的方法:

for SCOPE in system,global,local ; do
   EDITOR=/bin/cat git config --${SCOPE} --edit >> /path/to/my_git_config_file
done

获取配置值并将其连接成INI格式文件,可由git读取。


0
请确保使用 Git 2.27 (Q2 2020),因为 git config --list 将更加健壮:配置 API 混合使用 int 和 size_t 类型来表示它解析的各种文本的长度,现已更新为在整个过程中使用正确的类型(即 size_t)。

请查看 提交 348482d, 提交 6a9c235, 提交 f011a96, 提交 6c7e696, 提交 f5914f4, 提交 021ba32 (2020年4月10日) 由 Jeff King (peff) 提交。
(由 Junio C Hamano -- gitster -- 合并于 提交 342bc9e, 2020年4月28日)

config:使用size_t来存储解析变量baselen
由Jeff King签署
大多数配置解析基础设施的限制仅限于内存大小,因为它逐个字符地解析,为键、值等构建strbufs。
唯一的例外是我们在git_parse_source()中保留的"baselen"值,它是一个int类型。
它存储了基础的长度,然后我们可以通过截断到baselen并附加字符来添加单个键名(通过strbuf_setlen())。
但是,由于它是一个int类型,如果我们看到一个非常长的section或subsection,可能会导致整数溢出,变成负数。
当我们将其传递给strbuf_setlen()时,这个负值会被隐式转换为size_t,从而创建一个非常大的值,并触发一个BUG。例如: $ { printf '[foo "' perl -e 'print "a" x 2**31' echo '"]bar = value' } >huge $ git config --file=huge --list fatal: BUG: strbuf_setlen() beyond buffer 虽然这显然是一个我们不关心支持的愚蠢情况,但有几个原因值得修复它,即切换到size_t
- 我们应该尽量避免触发BUG断言 - 避免整数截断或溢出可以树立一个好的榜样,并使得更容易审计代码以查找更重要的问题 - BUG的结果是在这种情况下发生的,因为我们变成了负数。如果我们使用2**32个subsection,我们将变成一个小的正数值,并且实际上会生成错误的输出(我们的键的subsection将被截断)。

并且:

config: reject parsing of files over INT_MAX

Signed-off-by: Jeff King

While the last few commits have made it possible for the config parser to handle config files up to the limits of size_t, the rest of the code isn't really ready for this. In particular, we often feed the keys as strings into printf "%s" format specifiers. And because the printf family of functions must return an int to specify the result, they complain. Here are two concrete examples (using glibc; we're in uncharted territory here so results may vary):

Generate a gigantic .gitmodules file like this:

git submodule add /some/other/repo foo
{
        printf '[submodule "'
        perl -e 'print "a" x 2**31'
 echo '"]path = foo'
} >.gitmodules
git commit -m 'huge gitmodule'

then try this:

$ git show
BUG: strbuf.c:397: your vsnprintf is broken (returned -1)

The problem is that we end up calling:

strbuf_addf(&sb, "submodule.%s.ignore", submodule_name);

which relies on vsnprintf(), and that function has no way to report back a size larger than INT_MAX.

Taking that same file, try this:

git config --file=.gitmodules --list --name-only

On my system it produces an output with exactly 4GB of spaces. I confirmed in a debugger that we reach the config callback with the key intact: it's 2147483663 bytes and full of a's. But when we print it with this call:

printf("%s%c", key_, term);

we just get the spaces.

So given the fact that these are insane cases which we have no need to support, the weird behavior from feeding the results to printf even if the code is careful, and the possibility of uncareful code introducing its own integer truncation issues, let's just declare INT_MAX as a limit for parsing config files.

We'll enforce the limit in get_next_char(), which generalizes over all sources (blobs, files, etc) and covers any element we're parsing (whether section, key, value, etc). For simplicity, the limit is over the length of the _whole_ file, so you couldn't have two 1GB values in the same file. This should be perfectly fine, as the expected size for config files is generally kilobytes at most.

With this patch both cases above will yield:

fatal: bad config line 1 in file .gitmodules

That's not an amazing error message, but the parser isn't set up to provide specific messages (it just breaks out of the parsing loop and gives that generic error even if see a syntactic issue). And we really wouldn't expect to see this case outside of somebody maliciously probing the limits of the config system.


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接