Решение, которое я придумал, основано на ответе Скотта Велдона. Поскольку это не было напрямую применимо к моему случаю, я адаптировал 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
*: Изменения по сравнению с исходным кодом включают:
- Работает с пробелами в путях (особенно интересно в Windows)
- Правильно анализирует пары ключ-значение из
.gitconfig
(не читать строки с for
, используйте вместо этого while read
)
- Проверяет
.gitconfig
файлов из корня в локальный каталог, а не наоборот
- Вызывает хук только при первоначальном клонировании, а не при каждой проверке
- Вывести настройки конфигурации, которые применяются на
git clone
person
TheOperator
schedule
06.11.2016