ChatGPT解决这个技术问题 Extra ChatGPT

为所有子文件夹设置 git config 值

git

我知道可以设置覆盖用户级配置的 per-repo 配置(即 /path/to/my/repo/.gitconfig 覆盖 ~/.gitconfig)。是否可以设置 git configs 来覆盖给定文件夹的所有子文件夹的用户级设置?即,我有

|--topLevelFolder1
|--\
|   ---.gitconfig_override
|--\
|   ---childFolder1
|       \---[...]
|--\
|   ---childFolder2
|       \---[...]

我希望 .gitconfig_override 中定义的设置适用于 childFolder1childFolder2

我这样做的动机如下:我有一台工作笔记本电脑,我也会在业余时间用于个人项目。我所有的工作代码都嵌套在一个文件夹中。当我推动工作 git repos 时,我需要使用我的工作角色 - 工作登录而不是姓名,以及工作电子邮件。当我推送到我自己的个人 (github) 存储库时,我想用我的真实姓名和个人电子邮件这样做。

我想到的其他可能的解决方案(和问题):

为“工作”和“娱乐”创建单独的用户,适当地设置他们的用户级别设置,并在我切换上下文时以适当的用户身份登录(麻烦,而且我很容易忘记切换)

创建一个在“workFolder”中搜索 git repos 的脚本,并添加/更新他们的 .gitconfig 文件以保存适当的详细信息(如果我创建了一个 repo 并忘记在推送之前运行脚本,我将作为错误的人推送)

“hack” git,这样每次它创建一个 repo 时,它都会检查文件路径,并在适当的情况下更新 .gitconfig 文件(复杂、混乱,而且几乎可以肯定是错误的做法——另外,我不会有第一个线索如何去做!)

我检查了 this question,它似乎只包含单个 repos 的解决方案,而不是多个。希望有人会看到这个错过了这个问题的问题!

你会和“work you”和“personal you”在同一个存储库上工作吗?如果不是,您链接到的问题包含我要给出的答案。您的 --global 用户设置应包含您更多使用的身份。应该使用另一个身份的每个存储库都应该相应地设置 user.nameuser.email
我永远不会与两个不同的用户在同一个 repo 中工作——每个 repo 要么是“工作”,要么是“home”——但问题在于(至少对于工作而言)我有 35 个 repos 之类的东西,并且我更经常地添加。我可以在每个现有存储库中添加 user.nameuser.email 设置,并设置一个 cron 脚本以将它们添加到任何新添加的存储库中,但如果我可以将它们设置在一个地方会容易得多“过滤”到子文件夹中的任何存储库。
@scubbo,请查看答案,因为 Git 已更改,可能会为您的问题提供不同的答案。
感谢您的提醒!我刚刚更改了接受的答案。

Y
Yennefer

正如 NateEag's edit 所提到的,git 的 Conditional Includes 非常适合这一点。因为这个答案是 git < 上的人的答案。 2.13,这是为那些拥有较新版本的人准备的。

首先,在某个位置创建一个新的配置文件,其中包含要在子文件夹中生效的设置 - 使用原始问题的文件夹,假设它位于 ~/topLevelFolder1/.gitconfig_include

~/.gitconfig 中,添加:

[includeIf "gitdir:~/toplevelFolder1/"]
    path = ~/topLevelFolder1/.gitconfig_include

~/topLevelFolder1 的任何子文件夹现在都将包含 ~/toplevelFolder1/.gitconfig_include 中的配置 - 无需手动更改每个子文件夹的存储库中的 .git/config。 (这不会 覆盖 子文件夹配置中的任何内容 - 它只是 添加 到它,正如“包含”所暗示的那样。)

笔记:

此设置应位于您要在 ~/.gitconfig 中覆盖的配置之后,因为 includeIf 将被其后的任何配置再次覆盖。

仅当您位于给定路径下的存储库中时,此设置才包含该文件。如果您在任何非存储库子路径中,它将被忽略。

gitdir 条件中的尾部正斜杠 (/) 很重要。

git config --list 非常适合测试它。您将在输出中的 includeIf 行下方看到任何覆盖。您还可以使用例如 git config --get user.email 检查特定条目

在适用于 Windows 的 Git 上,使用 ~/ 指定相对于用户目录的路径,使用 Windows 样式的驱动器指定绝对路径,例如 C:/ 仅使用正斜杠。反斜杠和 Unix 风格的挂载点(如 /c/)不起作用。此外,在 includeIf 部分中,您必须指定大小写正确的路径,因为比较区分大小写。


gitdir 条件中的尾部斜杠 (/) 很重要。
This 应标记为该问题的正确答案。由于提到了 includeIf(以及一些尝试和错误),我现在已经在我的工作 PC 上配置了一个特定的文件夹树,其中每个 Git 操作都将我标识为我的个人帐户并使用我的个人 SSH 密钥,以及用于我个人 PC 上工作内容的类似文件夹。同时,每个系统的其余部分在两台机器上都使用适当的电子邮件、名称和 SSH 密钥。我只希望我不止一次赞成这个答案..(:
if 部分真的有必要吗?如果引用的 path 不存在,则该条目似乎被忽略。
如果只有 git 只是做了合乎逻辑的事情并遍历树在每个父目录中寻找 .git 目录......
@OliverPearmain 目标不是在文件存在时包含该文件,而是在给定路径下的存储库中包含该文件。
N
NateEag

编辑:Git 2.13 引入了 conditional includes,旨在解决这个确切的问题。

为了历史的缘故,我的原始答案保留在下面(并且用户坚持使用旧版本的 git)。

=====================================

根据阅读 gitconfig 手册页,不支持您想要的确切行为。

但是,从 git 1.7.12 开始,Git 从 four different sources 读取配置数据,其中两个是用户特定的:

$XDG_CONFIG_HOME/git/config~/.gitconfig~/.gitconfig 中的条目会覆盖 $XDG_CONFIG_HOME/git/config 中的条目。

这意味着您可以将您的个人 gitconfig 存储在 $XDG_CONFIG_HOME/git/config 并将特定于机器的覆盖放在 ~/.gitconfig 中。就像是

[user]
    email = username@example.com

~/.gitconfig 中的内容应涵盖您的电子邮件案例。

请注意,如果 $XDG_CONFIG_HOME 未设置,git 将查找 ~/.config/git/config

这对我很有效,因为我在工作机器上只有两个个人存储库(我的 emacs 配置和我的 dotfiles)。如果您经常将个人存储库添加到您的工作机器,这对您来说可能还不够好。

在这种情况下,围绕 git initgit clone 的自定义包装器将是您的最佳选择。

$PATH 上名称与“git-*”匹配的任何二进制文件都可以作为 git 命令调用,因此您只需要一对 shell 脚本,使用所有传递的参数调用原始命令,然后将正确的配置文件复制到.git/config


一些 git 设置可以通过设置环境变量来控制。它们覆盖配置文件中的值。为每个目录层次结构设置/取消设置环境变量的一个非常好的实用程序是 direnv。有关所有详细信息,请参阅下面的答案。
A
Ajay M

您可以使用 direnv 命令设置适用于所有子文件夹的环境变量。您可以在该目录层次结构中的任何位置。如果您尝试设置的 git 设置可以由环境变量控制,那么您很幸运。

阅读direnv基本页面http://direnv.net/,为您的 shell 进行设置。对于 zsh,只需将此行粘贴在 .zshrc 的底部并重新启动 shell 即可。

eval "$(direnv hook zsh)"

检查您想要的 git 设置是否可以由环境变量控制。您似乎想要控制特定目录树的 author.email,它由环境变量 GIT_AUTHOR_EMAIL 控制。注意,环境变量优先于配置。 git 支持的环境变量的完整列表在这里:https://git-scm.com/book/en/v2/Git-Internals-Environment-Variables

由于 direnv 的页面指定,在层次结构的根目录创建一个名为 .envrc 的文件;在您的情况下,topLevelFolder1

例如:

echo export GIT_AUTHOR_EMAIL=myotheremail@esp.com > .envrc

“允许” envrc:direnv allow . 就是这样!

每次跳入层次结构时,direnv 都会找到上述 .envrc 文件并加载它。

$ cd ~/topLevelFolder1/childFolder1/project_name
direnv: loading ../../../.envrc
direnv: export +GIT_AUTHOR_EMAIL

$ echo ${GIT_AUTHOR_EMAIL}
myotheremail@esp.com

跳出目录结构,direnv 将卸载那些变量

cd ~
direnv: unloading

C
Community

git config (.git/config, ~/.gitconfig ...) 中的 [include] 部分就是您要查找的内容。

[include]
    path = /path/to/foo.inc ; include by absolute path
    path = foo ; expand "foo" relative to the current file
    path = ~/foo ; expand "foo" in your $HOME directory

查看详细回答的问题:Is it possible to include a file in your .gitconfig

请参阅 git-config 文档:http://git-scm.com/docs/git-config#_includes

编辑

添加 childFolder1/.git/configchildFolder2/.git/config

[include]
    path = ../.gitconfig_override

好的 - 所以这解决了仅在一个地方(在 ../.gitconfig_override 中)定义 user.nameuser.email 的问题,但我认为它实际上并没有回答原始问题?如果 childFolder1childFolder2parentFolder 的子级,我正在寻找一种在 parentFolder 中设置配置值的方法,该值将过滤到任何以子文件夹为根的存储库。
作为 NateEag pointed out,这仅在 Git 2.13 中引入。 (Git 2.13.0 日期为 2017 年 5 月 9 日。)因此,如果阅读此答案的人想知道为什么它对他们不起作用,可能是他们使用的是旧版本的 Git。
请注意,我最近遇到了一个问题,这些条件包含似乎没有得到尊重。问题是 git(至少,我在 MacOSX 上的安装 - 2.17.0)似乎需要在目录路径上使用斜杠。