【问题标题】:Set git config values for all child folders为所有子文件夹设置 git config 值
【发布时间】:2014-02-13 23:29:12
【问题描述】:

我知道可以设置覆盖用户级配置的 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
  • 我永远不会在同一个仓库中与两个不同的用户一起工作——每个仓库要么是“工作”,要么是“家”——但问题在于(至少对于工作而言)我有 35 个 repos 之类的东西,并且会定期添加。我可以在每个现有的 repos 中添加 user.nameuser.email 设置,并设置一个 cron 脚本将它们添加到任何新添加的 repos 中,但如果我可以将它们设置在一个地方会容易得多“过滤”到子文件夹中的任何存储库。
  • @scubbo,请查看答案,因为 Git 已更改,可能会为您的问题提供不同的答案。
  • 感谢您的提醒!我刚刚更改了接受的答案。

标签: git


【解决方案1】:

正如NateEag's edit 所提到的,git 的Conditional Includes 非常适合这个。由于该答案是 git

首先,在某个地方创建一个新的配置文件,其中包含要在子文件夹中生效的设置 - 使用原始问题的文件夹,假设它位于 ~/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
  • Git for Windows 上,使用 ~/ 指定相对于您的用户目录的路径,并使用 Windows 样式的驱动器指定绝对路径,例如 C:/ 仅使用正斜杠。反斜杠和像/c/ 这样的Unix 风格的挂载点不起作用。此外,在includeIf 部分中,您必须指定大小写正确的路径,因为比较区分大小写

【讨论】:

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

您可以使用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

“允许”环境: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

【讨论】:

    【解决方案3】:

    编辑: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。有关所有详细信息,请参阅下面的答案。
    【解决方案4】:

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

    [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
    

    【讨论】:

    • OK - 所以这解决了仅在一个地方(../.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)似乎需要在目录路径上使用斜杠。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-21
    • 2011-05-15
    • 1970-01-01
    • 2011-12-15
    相关资源
    最近更新 更多