Git配置与目录范围,包含多个仓库

19
情况如下:
  • 我在多个领域编写代码,例如专业和业余时间。这些由我的计算机上不同的目录表示。
  • 每个领域都包含多个Git存储库,在一个域目录内的分层目录结构中。
针对每个领域,我想使用不同的电子邮件地址作为作者/提交者信息的一部分。也就是说,我希望我的私人地址列在我的业余项目中,将公司地址列在我的专业项目中。 git config 知道 3 个范围:仓库、全局和系统范围。我基本上需要第四个范围,介于仓库和全局之间,代表存储库组(或文件系统中的目录)。
似乎 git config 不允许这样做。 当然,我可以针对每个存储库设置电子邮件地址,但我想避免每次设置或克隆存储库时进行这个手动步骤。其中一个选项是编写包装 git init / clonegit config 的脚本,还有其他想法吗?

3个回答

26

根据https://dev59.com/I2855IYBdhLWcg3wpmLw#44036640的说法,我认为我找到了一种它可以工作的方式。

首先,您为不同的“自定义范围”(例如专业,休闲等)创建不同的配置文件,并为每个范围添加所需的用户配置。

# ~/all-projects.gitconfig
[user]
    name = TheOperator
# ~/professional.gitconfig
[user]
    email = yourname@yourwork.com
# ~/freetime.gitconfig
[user]
    email = yourname@private-email.com

然后,在您的标准git配置文件中添加以下行:

# ~/.gitconfig
[include]
    path = all-projects.gitconfig
[includeIf "gitdir/i:c:/work/"]
    path = professional.gitconfig
[includeIf "gitdir/i:c:/freetime/"]
    path = freetime.gitconfig 

gitdir/i之后的目录应该与您的项目组的父目录相匹配。在我的例子中,您应该将git仓库存储在freetime-domains下,例如c:/freetime/my-freetime.domain/.git


2
请注意,您可以在“~/.gitconfig”中设置默认值:文件中后面的值将覆盖先前的值(至少在当前的Git实现中),因此“all-projects.gitconfig”是多余的。 - Epic Wink
@Epic 你说得对,对于我的例子来说,将所有项目配置中的值添加到用户的.gitconfig中是可能的。但是如果有多个用户想要使用此项目配置(例如,如果all-project不包含"user.email"而是其他值,例如textconv-Rules等),那么这将是疯狂的。 - Radon8472

5
我想到的解决方案受到了Scott Weldon的回答的启发。由于它不适用于我的情况,我改编了钩子的bash脚本并改善了一些部分*。
假设以下目录结构位于主目录中:
~
   .gitconfig           // [init] templatedir
   .git-template
      hooks
         post-checkout  // our bash script
   MyDomain
      .gitconfig        // [user] name, email

最初我告诉Git我的模板目录在哪里。在Windows上,你可能需要指定绝对路径 (C:/Users/MyUser/.git-template)。

git config --global init.templatedir '~/.git-template'

~/MyDomain/.gitconfig 中,我存储了该目录(domain)的配置信息,这些配置应用于其内部及其子目录下的所有仓库。
cd ~/MyDomain
git config --file .gitconfig user.name "My Name"
git config --file .gitconfig user.email "my@email.com"

有趣的部分是 post-checkout bash 脚本,它定义了 post-checkout 钩子。我使用了一个自定义的 user.inferredConfig 标志,只在 git clone 上执行一次,而不是重复执行(在 git checkout 上)。当然也可以创建一个单独的文件来表示该状态。

#!/bin/bash

# Git post-checkout hook for automated use of directory-local git config
# https://dev59.com/xVkS5IYBdhLWcg3wKzqq#40450106

# Check for custom git-config flag, to execute hook only once on clone, not repeatedly on every checkout
if grep -q "inferredConfig" .git/config
then
    exit
fi

# Automatically set Git config values from parent folders.
echo "Infer Git configuration from directory..."

# Go upwards in directory hierarchy, examine all .gitconfig files we find
# Allows to have multiple nested .gitconfig files with different scopes
dir=$(pwd)
configFiles=()
while [ "$dir" != "/" ]
do
    # Skip first directory (the newly created Git repo)
    dir=$(dirname "$dir")
    if [ -f "$dir/.gitconfig" ]
    then
        configFiles+=("$dir/.gitconfig")
    fi
done

# Iterate through configFiles array in reverse order, so that more local configurations override parent ones
for (( index=${#configFiles[@]}-1 ; index>=0 ; index-- )) ; do
    gitconfig="${configFiles[index]}"

    echo "* From $gitconfig:"
    # Iterate over each line in found .gitconfig file
    output=$(git config --file "$gitconfig" --list)
    while IFS= read -r line
    do
        # Split line into two parts, separated by '='
        IFS='=' read key localValue <<< "$line"

        # For values that differ from the parent Git configuration, adjust the local one
        parentValue=$(git config $key)
        if [ "$parentValue" != "$localValue" ]
        then
            echo "  * $key: $localValue"
            git config "$key" "$localValue"
        fi
    done <<< "$output"

    # Set custom flag that we have inferred the configuration, so that future checkouts don't need to do it
    git config user.inferredConfig 1
done

*: 改动的部分包括:
  1. 支持路径中的空格(在Windows上特别有用)
  2. 正确解析 .gitconfig 中的键值对(不要使用 for 读取行改用 while read 迭代
  3. 从根目录到本地目录检查 .gitconfig 文件,而不是反过来
  4. 仅在初始克隆时调用钩子,而不是每次检出时都调用
  5. 输出应用于 git clone 的配置设置

0
作为一个简单的解决方案,使用类似autoenv(抱歉自我宣传)的东西来使用环境变量设置您的邮件地址:
echo 'export GIT_AUTHOR_NAME="Your name"' > professional/.env
echo 'export GIT_AUTHOR_EMAIL="you@example.com"' >> professional/.env
cd professional

谢谢这个提示。在这里,我想采用不需要外部工具的解决方案,但是autoenv看起来在其他地方可能会有用 :) - TheOperator
autoenv和direnv看起来非常有趣!但是它们只在shell中工作,如果我使用GUI git客户端怎么办? - Iliyan Georgiev

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