Конфигурация Git с областью каталога, содержащей несколько репозиториев

Ситуация следующая:

  • У меня есть несколько доменов, в которых я пишу код, например. профессиональное и свободное время. Они представлены разными каталогами на моем компьютере.
  • Каждый из этих доменов содержит несколько репозиториев Git в иерархической структуре каталогов внутри одного из каталогов домена.

Для каждого домена я хочу использовать другой адрес электронной почты как часть информации об авторе/коммиттере. То есть я хочу, чтобы мой личный адрес был указан в моих проектах в свободное время, а адрес моей компании — в моих профессиональных.

git config знает 3 области видимости: репозиторий, глобальную и общесистемную. Что мне в основном нужно, так это 4-я область между репозиторием и глобальным, представляющая группу репозиториев (или просто каталог в файловой системе).

Похоже, git config этого не позволяет. Конечно, я мог бы установить адрес электронной почты для каждого репозитория, но я хочу избежать этого ручного шага каждый раз, когда я настраиваю или клонирую репозиторий. Одним из вариантов было бы написать сценарий, который обертывает git init/clone и git config, есть ли другие идеи?


person TheOperator    schedule 26.10.2016    source источник


Ответы (3)


на основе https://stackoverflow.com/a/44036640/2377961 я думаю, что нашел способ, как это может работать.

сначала вы создаете разные файлы конфигурации для своих «пользовательских областей» (например, профессиональных, свободных и т. Д.) И добавляете желаемую пользовательскую конфигурацию для каждой области.

# ~/all-projects.gitconfig
[user]
   name = TheOperator

.

# ~/professional.gitconfig
[user]
   email = [email protected]

.

# ~/freetime.gitconfig
[user]
   email = [email protected]

чем вы добавляете такие строки в свой стандартный gitconfig:

# ~/.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-репозитории для доменов свободного времени, например. "c:/свободное время/мое-свободное время.домен/.git"

person Radon8472    schedule 07.03.2018
comment
Обратите внимание, что вы можете установить значения по умолчанию в ~/.gitconfig: более поздние значения переопределяют более ранние значения в файле (по крайней мере, в текущей реализации Git), поэтому all-proects.gitconfig является избыточным. - person Epic Wink; 16.11.2019
comment
@Epic, вы правы, для моего примера можно добавить значения из конфигурации всех проектов в пользовательские .gitconfig. Но это было бы безумием, если бы более одного пользователя хотели использовать эту конфигурацию проекта (например, если all-project содержит не user.email, а другие значения, например, textconv-Rules и т. д. - person Radon8472; 18.11.2019

Решение, которое я придумал, основано на ответе Скотта Велдона. Поскольку это не было напрямую применимо к моему случаю, я адаптировал 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 я храню конфигурацию для этого каталога (домен), которая должна применяться ко всем репозиториям внутри него и его подкаталогам.

cd ~/MyDomain
git config --file .gitconfig user.name "My Name"
git config --file .gitconfig user.email "[email protected]"

Интересная часть — скрипт post-checkout bash, определяющий хук после оформления заказа. Я использовал собственный флаг user.inferredConfig, чтобы выполнить его только один раз (на git clone), а не повторно (на git checkout). Конечно, также можно было бы создать отдельный файл для представления этого состояния.

#!/bin/bash

# Git post-checkout hook for automated use of directory-local git config
# https://stackoverflow.com/a/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
person TheOperator    schedule 06.11.2016

В качестве простого решения используйте что-то вроде autoenv (извините за саморекламу), чтобы установить свой почтовый адрес с помощью переменные окружения:

echo 'export GIT_AUTHOR_NAME="Your name"' > professional/.env
echo 'export GIT_AUTHOR_EMAIL="[email protected]"' >> professional/.env
cd professional
person das_j    schedule 27.10.2016
comment
Спасибо за эту подсказку. Здесь я хотел бы использовать решение, которое не требует внешних инструментов, но похоже, что autoenv может быть полезен в другом месте :) - person TheOperator; 06.11.2016
comment
autoenv и direnv выглядят очень интересно! Но разве они не работают только в оболочке? Что, если я использую клиент git с графическим интерфейсом? - person Iliyan Georgiev; 24.09.2017